C++ socket writing too many characters - c++

This code is embedded in a "chat room" program using sockets. It is reading from the client (myFD) and successfully appending a username to the front.
However, I have a problem writing extra characters in the write buffer. What was sent last time is still stored and also sending.
For example, the first time I'd send (and write correctly)
UN: Hello.
But on the second try, when I'd write, say, "NOT", the message sent would be:
UN: NOTlo
The cout statement correctly "cout's" without the "lo" at the end, but the clients receive the "lo" at the end. Am I overlooking something simple?
Code Below:
while ( (amount_read = read(myFD, buffer, 1024)) > 0)
{
total = 0;
strcpy(second, "");
strcpy(second, username);
total += unLength;
strcat(second, ": ");
total += 2;
strcat(second, buffer);//, amount_read);
total += amount_read;
cout << second << endl;
write(myFD, second, total);
}
Thanks!

Your string is not null terminated that's why you print old string. You can fix it adding \0 at the end of string buffer[amount_read]=0 or just clear whole string before next iteration.
To clear buffer you can use memset (buffer,'\0', 1024). Maybe it's not fastest way but prevent storing rubbish or data that shouldn't be hosted longer than it's necessary.

You are not adding in '\0' correctly.
I guess your transmit looks like this write(myFD, buffer, strlen(buffer)), then you will send everything but the 0 terminator. It works the first time because you probably did a memset.
buffer[amount_read]=0; will probably fix it.

Related

Not overwriting elements in arrays

I am writing code for a program we are supposed to make in my computer science course I am taking, where we are learning C++. In this program, I'm trying to get a user to enter flavours of popcorn they may like, but without exceeding 10 (or 9) characters. When I tried including flavours with > 10 chars, the program would not result in an error or work properly, but would just store the chars exceeding 10 into the next element in the array. How can I stop the program from doing this?
#define POP_COUNT 5
#define POP_SIZE 10
int main() {
char popcorn[POP_COUNT][POP_SIZE];
fputs("Enter your 5 favourite popcorn flavours: \n", stdout);
for (int i = 0; i < POP_COUNT; i++) {
fgets(popcorn[i], POP_SIZE, stdin);
popcorn[i][POP_SIZE - 1] = 0;
}
cout << popcorn[0] << endl;
cout << popcorn[1] << endl;
fputs("Your favourite flavours are: \n", stdout);
for (int i = 0; i < POP_COUNT; i++) {
fputs(popcorn[i], stdout);
}
}
Your issue arises from the normal behavior of fgets(). It will not read more characters than a buffer of the size you specify can accommodate, including space for a terminator. Whatever it does not read on a given call remains waiting in the stream, and will be read on the next call.
To address this, you must first detect it. You can do that by checking whether a newline was stored in the destination buffer. If so, then you're good, but if not, then only a partial line has been read. Note, too, that you do not need to manually insert a terminator -- fgets() will always include a terminator on success.
If you just want to discard any extra characters, then in the second case you must do exactly that -- read and ignore additional characters until either you have read a newline, or you reach the end of the file.

Qt reading serial input then splitting it into separate variables

I'm working on Qt, however I have come across an issue which for the life of me I cant fix at all. I have tried many different combinations to my code, but it still hasn't given me the output I'm looking for. I am hoping someone can help me.
QStringList buffer_split = serialBuffer.split(","); // split the serialBuffer string, parsing with ',' as the separator
// Check to see if there less than 3 tokens in buffer_split.
// If there are at least 3 then this means there were 2 commas,
// means there is a parsed temperature value as the second token (between 2 commas)
if(buffer_split.length() < 3){
// no parsed value yet so continue accumulating bytes from serial in the buffer.
serialData = arduino->readAll();
serialBuffer = serialBuffer + QString::fromStdString(serialData.toStdString());
serialData.clear();
}else{
// the second element of buffer_split is parsed correctly, update the temperature value on temp_lcdNumber
serialBuffer = "";
qDebug() << buffer_split << "\n";
parsed_data = buffer_split[1];
}
The above solution has worked for me, in turn I am reading the values being sent over the serial port such as:
0,0,0,0,0,0
Above is how parsed_data is reading the information from the serial port, which is correct.
The issue I am having, is splitting that, then storing them in separate variables to start some if statements. so far I can't seem to get it to work.
If anyone can help me I would be grateful
Thank You
You don't need an extra parsed_data variable buffer_split stores them, all you just need int num1 = buffer_split[0].toInt(); int num2 = buffer_split[1].toInt(); ...

I don't understand buffered output and cout

I've got a really simple program that prints lines using cout and sleeps after each line. All is well and good for about 7 iterations, as the buffer is clearly not flushed at any point. After then, what I assume is only part of the buffer is flushed on every iteration.
I have a few questions about this behaviour:
If the buffer is supposedly big enough to fit ~7 lines of output, why is the buffer flushed one line at a time?
If this buffer is indeed flushed in this way, what is the advantage to this? Why isn't the whole buffer flushed at once?
Is it just a coincidence that the exact same number of characters are flushed to the output as my line length, or is the cout buffer internally flushed based on end-of-line delimiters such as '\n'?
int main(){
for(int i = 0; i < 100; ++i){
std::cout << "This is line " << i << '\n';
Sleep(1000);
}
return 0;
}
You seem to assume that the buffer will not be written until it is full. Probably what happens is that an asynchronous write is started with as little as one output byte. The empty buffer space is used to receive characters while the asynchronous write is in progress. When the current write completes, if/when there are additional characters in the buffer, a new asynchronous write is started. The process would only need to block on writing if the buffer got full.

EOF - scanf and printf

I'm tring to do a simple exercise here, but i need to understand how EOF works first.
void main()
{
char s1[1000];
while (scanf("%s", s1)!=EOF)
;
printf("%s",s1);
}
The idea is to have multiple lines in input, and display them.
The problem I have is that if I put
Hello World
This is stackoverflow
When printf is called, it only prints
stackoverflow
Why isn't it printing everything and how do I make it print?
Regards
Remove the semicolon ;:
while (scanf("%s", s1)!=EOF)
printf("%s",s1);
Note that this will still exhibit odd behavior at end of file depending on how it ends exactly. Furthermore, it splits the input into words, which are separated by spaces or new lines. You may want to simply split into lines.
So you may be better served with for instance:
while (gets(s1)!=NULL)
puts(s1);
This code fragments reads your input line by line until end-of-file.
To read everything (or as much as your buffer can hold), you can use:
char s1[1000] = "";
fread(s1, sizeof(s1) - 1, 1, stdin);
puts(s1);
However, my preferred method of reading a text file is:
using namespace std;
string line;
while (getline(cin, line))
{
cout << line << endl;
}
That is because usually I want to process a file line by line, and getline with a string ensures the line buffer is always big enough.
You probably want this:
char s1[1000][20];
int i = 0 ;
while (!feof(stdin))
fgets(s1[i++], 20, stdin) ;
int j ;
for (j = 0; j < i; j++)
printf("%s\n", s1[j]);
Here you can enter at most 1000 lines that are maximum 19 characters long.
What you have is a loop that reads words into a buffer until it reaches EOF (and does nothing with those words), followed by a printf to print the contents of the buffer. The printf is after the loop (not in it), so executes once after the loop completes. At that time, the buffer will contain the last word read, so that is what gets printed.
The EOF return test means "nothing more to be read", which isn't necessarily an end of file (might be an error condition of some kind), but in practice that distinction can be ignored. Looping until your reading function returns EOF or NULL (depends on function) is good practice.
If you want to print each word as it is read, you need to put a printf in the loop.
If you want to store the words for later processing, you need to store them somewhere. That means declaring some storage space, or allocating space on the heap, and some bookkeeping to track how much space you've used/allocated.
If you want lines rather than words, you should use fgets instead of scanf("%s". Note that fgets returns NULL rather than EOF when there's nothing more to be read.
Because it only prints the last thing that is read from the file ("stackoverflow"). This is caused by the semicolon after the end of your while(...); - this means that you are doing while(...) { /* do nothing */} - which is probably not what you wanted
Also, printf("%s",s1)!='\0'; makes no sense at all. For one thing, printf returns the number of characters printed - '\0' is the value zero written as a character constant. And of course, doing != 0 of the result without some sort of use of the comparison is pretty much pointless too.
Use fgets instead of scanf if you want to read one line at at time. scanf will stop reading when it finds a whitespace. fgets will read till the end of the line.
Use fgets(). Simple and sweet
char buf[1000];
while (fgets(buf, sizeof buf, stdin) != NULL) {
fputs(buf, stdout);
}
Here is how end-of-file works in C. The input channels are called input streams; disk files and stdin are both input streams. The "end-of-file" state is a flag that a stream has, and that flag is triggered when you try to read from a stream, but it turns out there are no more characters in the stream, and there never will be any more. (If the stream is still active but just waiting for user input for example, it is not considered to be end-of-file; read operations will block).
Streams can have other error states, so looping until "end-of-file" is set is usually wrong. If the stream does go into an error state then your loop will never exit (aka. "infinite loop").
The end-of-file state can be checked by feof. However, some input operations also can signal an error as well as, or instead of, returning the actual data they were intended to read. These functions can return the value EOF. Usually these functions return EOF in both cases: end-of-file, and stream error. This is different to feof which only returns true in the case of end-of-file.
For example, getchar() and scanf will return EOF if it was end-of-file, but also if the stream is in an error state.
So it is OK to use getchar()'s result as a loop condition, but not feof on its own.
Also, it is sometimes not OK to use scanf() != EOF as a loop condition. It's possible that there is no stream error, but just that the data you requested wasn't there. For example, if you scan for "%d" but there are letters in the stream. Instead, it's better to check for successful conversion (scanf returns the number of successful conversions it performed). Then when you exit your loop, you can go on to call feof and ferror to see whether it was due to end-of-file, or error, or just unexpected input.

char array storing too many characters? (c++)

Doing a message program thing, and ran into a problem I don't understand with the buffer. The answer i'm sure is really simple but I just can't wrap my head around it. I'm trying to ask the user to type in a 10 digit name that will work as a username.
char myID[11]; // stores 10 characters plus newline at the end
char sendBuff[1024]
cout << "Enter your nickname(10 digits): ";
cin >> myID;
cin.ignore(1000, '\n'); //clears buffer, or so I thought
Then I get some actual text for the message, store it in tempCharArray, then combine the username and the message text using sprintf_s.
char tempCharArray[1024];
cin.getline( tempCharArray, 1024 );
sprintf_s(sendBuff, 1024, "%s: %s", myID, tempCharArray ); //combines username and message text into one line before being printed
Now, my problem is that if I type in a name longer than 10 digits, it will print out the entire name in the sprintf_s function, despite myID being only 10 characters. I do not at all understand this behavior...
For example if I type in "HelloKitty69420" into myID, and then "yoyoyo" into tempCharArray, I would expect it to print "HelloKitty: yoyoyo" because myID can only hold 10 characters, yet it prints "HelloKitty69420: yoyoyo".
What's going on?
I would comment on your overall strategy for accomplishing your goal (ie. it is definitely no the way I would go about it) but I will focus on an answer.
Firstly, you should use std::cin.width(10) to limit the number of characters actually stored and moved to myID.
Secondly, you seem to have been lucky in the above case. The overflow bytes were written into the second array sendBuff and sprintf was writing characters from both myID and sendBuff.
The reason the overflow bytes were written into the second array is that the compiler simply placed myID and sendBuff in memory regions that were contiguous. ie myID[1000] would be the same as sendBuff[1000-11]