Hey, I have a homework assignment in which I have to make a train ticket reservation system. I made a menu to display the trains currently available in the system (like a timetable). I wanted to use fix width columns, but regardless of what or how I try, the lines are just not aligned
Any idea why? Thanks for the help in advance
#Text output in terminal is not aligned with the set column width
62 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
This happened to me too, I played with the setw() and fixed it, I think I was not accounting for the last column or something: #cpp-help-text message
Sorry I can't help more, I suck, but if that helps any
This is how it the setw() looked when I fixed it
I am assuming my problem originates from setw switching between strings and integers
Because that’s where the problem occours
This is probably more of an issue that relates to utf8 if that's what encoding is being printed for that text. I believe setw()'s parameter corresponds to a byte length, not truly a character length. A utf-8 "character" could be anywhere from 1-4 bytes. If you notice where the alignment gets thrown off is anywhere a non-ascii character seems to exist in the string that comes before it
If you're allowed to use std::print, there's a pretty good chance it handles this correctly with utf8 text
I have tried it before with this:
void Menetrend::menetrendKiir() const { //FIXME: elcsúszik a kiírás
printf("Vonatok száma: %d\n", this->vonatokSzama);
printf("Vonatok:\n\n");
printf("%-15s%-13s%-23s%-25s%-17s%-18s%-16s%-2s\n",
"Név", "Vonatszám", "Indulási állomás", "Érkezési állomás",
"Indulási idő", "Érkezési idő", "Állapot", "Vagonok száma");
if (this->vonatokSzama == 0) {
printf("\x1b[37;41m%s\x1b[0m\n\n", "-----------------------------------------------------------------------------------------------------------------------------");
printf("Nincs egyetlen vonat sem!\n\n");
return;
} else {
printf("\x1b[37;40m%s\x1b[0m\n", "-----------------------------------------------------------------------------------------------------------------------------");
for (int i = 0; i < this->vonatokSzama; i++) {
printf("%-14s%-12d%-20s%-22s%-15s%-15s%-17s%-2d\n",
this->vonatok[i].getNev().c_str(), this->vonatok[i].getVonatSzam(),
this->vonatok[i].getIndulasiAllomas().c_str(), this->vonatok[i].getErkezesiAllomas().c_str(),
this->vonatok[i].getIndulasiIdo().getIdoString().c_str(), this->vonatok[i].getErkezesiIdo().getIdoString().c_str(),
this->vonatok[i].getAllapotString().c_str(), this->vonatok[i].getVagonokSzama());
}
}
printf("\n");
}
this is the result
;compile clang_trunk -std=c++23 -stdlib=libc++
#include <iostream>
#include <iomanip>
#include <ios>
#include <locale>
#include <print>
int main()
{
std::locale::global(std::locale("en_US.UTF-8"));
::printf("%-15s%-13s%-23s%-25s%-17s%-18s%-16s%-2s\n",
"Név", "Vonatszám", "Indulási állomás", "Érkezési állomás",
"Indulási idő", "Érkezési idő", "Állapot", "Vagonok száma");
::printf("%-15s%-13s%-23s%-25s%-17s%-18s%-16s%-2s\n",
"aaaa", "aaaa", "aaaa", "aaaa", "aaaa", "aaaa", "aaaa", "aaaa");
::printf("%-15s%-13s%-23s%-25s%-17s%-18s%-16s%-2s\n",
"Név", "aaaa", "aaaa", "aaaa", "aaaa", "aaaa", "aaaa", "aaaa");
::printf("\n");
std::cout << std::setw(15) << std::left << "Név"
<< std::setw(13) << std::left << "Vonatszám"
<< std::setw(23) << std::left << "Indulási állomás"
<< std::setw(25) << std::left << "Érkezési állomás"
<< std::setw(17) << std::left << "Indulási idő"
<< std::setw(18) << std::left << "Érkezési idő"
<< std::setw(16) << std::left << "Állapot"
<< std::setw(02) << std::left << "Vagonok száma" << '\n';
std::cout << std::setw(15) << std::left << "aaaa"
<< std::setw(13) << std::left << "aaaa"
<< std::setw(23) << std::left << "aaaa"
<< std::setw(25) << std::left << "aaaa"
<< std::setw(17) << std::left << "aaaa"
<< std::setw(18) << std::left << "aaaa"
<< std::setw(16) << std::left << "aaaa"
<< std::setw(02) << std::left << "aaaa" << '\n';
std::cout << std::setw(15) << std::left << "Név"
<< std::setw(13) << std::left << "aaaa"
<< std::setw(23) << std::left << "aaaa"
<< std::setw(25) << std::left << "aaaa"
<< std::setw(17) << std::left << "aaaa"
<< std::setw(18) << std::left << "aaaa"
<< std::setw(16) << std::left << "aaaa"
<< std::setw(02) << std::left << "aaaa" << '\n';
::printf("\n");
std::print("{:<15}{:<13}{:<23}{:<25}{:<17}{:<18}{:<16}{:<2}\n",
"Név", "Vonatszám", "Indulási állomás", "Érkezési állomás",
"Indulási idő", "Érkezési idő", "Állapot", "Vagonok száma");
std::print("{:<15}{:<13}{:<23}{:<25}{:<17}{:<18}{:<16}{:<2}\n",
"aaaa", "bbbb", "cccc", "dddd", "eeee", "ffff", "gggg", "hhhh");
std::print("{:<15}{:<13}{:<23}{:<25}{:<17}{:<18}{:<16}{:<2}\n",
"Név", "bbbb", "cccc", "dddd", "eeee", "ffff", "gggg", "hhhh");
}
Program Output
Név Vonatszám Indulási állomás Érkezési állomás Indulási idő Érkezési idő Állapot Vagonok száma
aaaa aaaa aaaa aaaa aaaa aaaa aaaa
calro | 79ms | c++ | x86-64 clang (trunk) | godbolt.org
it'll be easier to view the output of those from here since it's getting truncated in discord: https://godbolt.org/z/jfnWErvrM
int main()
{
std::locale::global(std::locale("en_US.UTF-8"));
::printf("%-15s%-13s%-23s%-25s%-17s%-18s%-16s%-2s\n",
"Név", "Vonatszám", "Indulási állomás", "Érkezési állomás",
"Indulási idő", "Érkezési idő", "Állapot", "Vagonok száma");
::printf("%-15s%-13s%-23s%-25s%-17s%-18s%-16s%-2s\n",
"aaaa", "a...
the middle row in all 3 is the one you can go off of as being correctly aligned/spaced apart. notice how the top two examples (printf and std::cout) are misaligned, but std::print() is aligned properly for all 3 rows... that just comes down to std::print / std::format internally handling utf-8 properly when working with unicode.
the reason this type of thing matters is that even though it seems like "Név" is 3 characters in length, it's size in bytes is 5. so the spacing gets thrown off just from that starting at the very beginning of the row.
He isn't
We can go up to C++17, std::print is C++20
Get it now
And indeed, if I remove letters suck as á é ó etc, and replace with a e o etc, then it works perfectly
I'll try to find a solution for this then, thanks
Most mondtam volna, hogy gyulának nem tűnik fel, csak gondolom a jporta 17-ig fordít, right?
✅

download fmtlib :^)
will check it out, thanks
His instructor didn't allow him to use sqlite because they(the instructor) couldn't understand what it did
So I doubt they will be allowed to use any libraries sadly
💀
if I don't tell him, he simply won't notice or realize

even if I used sqlite, he wouldn't have noticed I'm sure lol
Maximal Gyula, Minimal Effort ☝️

Tbh I doubt he will actually look at the whole codebase of 30+ students
You could grab a function like this https://stackoverflow.com/a/5117542
to get the number of code units instead of bytes, that would work for simple things (but not for complex unicode sequences with multiple combining characters)
He will for some for sure, but I'm almost certain that he will not look at mine
Like he didn't do it so far, but rejected other students' works so far
(also this is assuming you are actually using UTF-8, whiuch isn't the default in MSVC / VS)
Yeah, I think I tried to do something similar
what I did it I measured the "length" of the word I'm trying to print and then (after some math) set setw based on the return integer
but it didn't really work out
Correct
setlocale(LC_ALL, "hu_HU.utf8");
ah so you're not on windows
because windows + utf-8 + console is a whole other bag of worms 😄
Windows + utf8 is already a big enough bag 💀
Especially when I'm alternating between Manjaro(desktop) and Windows (portable)
Thankfully someone showed me how to set utf8 as default on win
@torn grotto Has your question been resolved? If so, type !solved :)
int utf8_length(const char *s) {
int i = 0, j = 0;
while (s[i]) {
if ((s[i] & 0xc0) != 0x80) j++;
i++;
}
return j;
}
std::string pad(int width, std::string s) {
int length = utf8_length(s.c_str());
int padding = std::max(width - length, 0);
s.resize(s.size() + padding, ' ');
return s;
}
int main()
{
st...
I'll put this in my random_useful.h
you could probably make it work with setw, too, but you'd have to account for setw padding based on the number of bytes
wow thank you
will try it later today
maybe I shouldn't have tried to make this function half past midnight
again, warning sticker, doesn't take into account if you have like combining marks as separate code units
for wide characters, there's a wcwidth function that sort of tells you this properly, but who wants to use wide characters 💀
works flawlessly, thanks again
@torn grotto Has your question been resolved? If so, type !solved :)
!solved