using brackets in printf not working correctly - c

I am using GCC 6.4 and my printf statement is as follows:
printf("Initial Colour: RGB(%s,%s,%s)\n",userdata[k],userdata[k+1],userdata[k+2]);
It prints )nitial Colour: RGB(1,0.0 which is wrong. Note where the second bracket is printed.
It should be Initial Colour: RGB(1,0.0) as expected.
If I use GCC 4.5 with the same printf, it prints as expected.
What should my printf look like?

You are reading a data file that was created on a Windows system. Lines are terminated by \r\n (carriage return, line feed). You are either processing this file on that same Windows system, but you are opening the file in binary ("rb") mode. Or, you are transferring the file to a Unix or Linux (or Mac) system and processing it there, but you are transferring it in a "binary" mode, that preserves the CRLF, without converting it to the Unix single-newline ('\n') convention.
Then, you are reading lines of text, perhaps with fgets. You are discarding the newline ('\n'), but you are not discarding the carriage return ('\r'). So, each line ends with \r.
Then, you are splitting up the line into fields userdata[0], userdata[1], userdata[2], ... . I'm not sure if you're splitting it up at commas or at whitespace, but in any case, the \r is remaining attached to the last field.
Finally, when you print out that last field userdata[k+2], that carriage return at the end of it is causing the cursor to return to the beginning of the line before the final ) is printed.
You can fix this in several ways:
Don't create the file with \r\n in the first place.
If processing the file on a Windows system, open it in text ("r" or maybe "rt") mode, not binary.
If transferring files from a Windows to a non-Windows system, use a "text" transfer mode that converts line endings.
When reading lines from the file, strip off trailing \r as well as \n characters.
If splitting fields on whitespace, include '\r' in the set of whitespace characters to split on. For example, if you are calling strtok, with separators " " or " \t", change to " \r" or " \t\r".
Now that you've posted code, I can be more specific.
To achieve #4, add the line
if (buffer[strlen(buffer)-1] == '\r') buffer[strlen(buffer) - 1] = '\0';
after the line where you strip off the \n.
To achieve #5, change your two strtok calls to
data = strtok(buffer, " \r");
and
data = strtok(NULL, " \r");
As a matter of fact, you could also change those two lines to
data = strtok(buffer, " \r\n");
and
data = strtok(NULL, " \r\n");
and then you wouldn't need the newline-stripping step at all.
One more thing: your usage of feof is wrong. See Why is while(!feof (fp)) always wrong?.

Related

Stripping newline character causes problems reading batchfile in c

FILE *in_file = fopen("batchfile", "r"); // read only
while( fgets (buf, MAX_BUFFER, in_file)!=NULL )
{
buf[strcspn(buf, "\n")] = 0;
printf("%s ", buf);
}
When I try to run this code without the buf[strcspn(buf, "\n")] = 0;, line, it runs properly and prints out the 3 lines of text in my batchfile. When I add this line to strip the newline character it only prints the last line of my file. Anyone know why this is happening?
Windows represents line breaks as the two-character sequence CR, LF (carriage return, line feed). Most other systems represent line breaks as a simple LF. In C, a CR is '\r' and a LF is '\n'.
When you open a text file on Windows (fopen without the b flag), the CR-LF sequence is converted into a simple '\n'. When you open a text file on Unix-like systems (including Linux, macOS, and some ports of Unix development tools to Windows), a CR is just an ordinary character. So if you read a Windows text file on Unix and you want to remove the line breaks, you need to remove both the '\n and the preceding '\r'.
Many terminals interpret LF as “go to the beginning of the next line” and CR as “go to the beginning of the current line”. So if you read and print a Windows text file, the CR characters are effectively invisible. If you read and print a Unix text file but remove the LF characters, the lines come out concatenated together without breaks. If you read and print a Windows text file, and you remove the LF characters but you keep the CR characters, each line overwrites the previous line. You can watch that happening stepping through your program in a debugger, or by adding fflush(stdout); sleep(1); after each printf call.
To support both Unix and Windows line endings, check if there's a '\r' before the '\n' and remove it.
size_t len = strlen(buf);
if (len > 0 && buf[len-1] == '\n') buf[--len] = 0;
if (len > 0 && buf[len-1] == '\r') buf[--len] = 0;

Reading \n as really Feed Line character from text file in C

I'm trying to read text file with C. Text file is a simple language file which works in embeded device and EACH LINE of file has a ENUM on code side. Here is a simple part of my file :
SAMPLE FROM TEXT FILE :
OPERATION SUCCESS!
OPERATION FAILED!\nRETRY COUNT : %d
ENUM :
typedef enum
{
...
MESSAGE_VALID_OP,
MESSAGE_INVALID_OP_WITH_RETRY_COUNT
...
}
Load Strings :
typedef struct
{
char *str;
} Message;
int iTotalMessageCount = 1012;
void vLoadLanguageStrings()
{
FILE *xStringList;
char * tmp_line_message[256];
size_t len = 0;
ssize_t read;
int message_index = 0;
xStringList = fopen("/home/change/strings.bin", "r");
if (xStringList == NULL)
exit(EXIT_FAILURE);
mMessages = (Message *) malloc(iTotalMessageCount * sizeof(Message));
while ((read = fgets(tmp_line_message, 256, xStringList)) != -1 && message_index < iTotalMessageCount)
{
mMessages[message_index].str = (char *) malloc(strlen(tmp_line_message));
memcpy(mMessages[message_index].str, tmp_line_message, strlen(tmp_line_message) -1);
message_index++;
}
fclose(xStringList);
}
As you se in the Sample from text file i have to use \n Feed Line character on some of my lines. After all, i read file successfuly. But if i try to call my text which has feed line \n, feed line character just printed on device screen as \ & n characters.
I already try with getline(...) method. How can i handle \n character without raising the complexity and read file line by line.
As you se in the Sample from text file i have to use \n Feed Line
character on some of my lines.
No, I don't see that. Or at least, I don't see you doing that. The two-character sequence \n is significant primarily to the C compiler; it has no inherent special significance in data files, whether those files are consumed by a C program or not.
Indeed, if the system recognizes line feeds as line terminators, then by definition, it is impossible to embed a literal line feed in a physical line. What it looks like you are trying to do is to encode line feeds as the "\n" character sequence. That's fine, but it's quite a different thing from embedding a line feed character itself.
But after all, i read file successfuly.
But if i try to call my text which has feed line \n, feed line
character just printed on device screen as \ & n characters.
Of course. Those are the characters you read in (not a line feed), so if you write them back out then you reproduce them. If you are encoding line feeds via that character sequence, then your program must decode that sequence if you want it to output literal line feeds in its place.
I already try with getline(...) method. How can i handle \n character
without raising the complexity and read file line by line.
You need to process each line read to decode the \n sequences in it. I would write a function for that. Any way around, however, your program will be more complex, because the current version simply doesn't do all the things it needs to do.

End of line character / Carriage return

I'm reading a normal text file and write all the words as numbers to another text. When a line finishes it looks for a "new line character (\n)" and continues from the new line. In Ubuntu it executes perfectly but in Windows (DevC++) it cannot operate the function. My problem is the text in Windows which I read haven't got new line characters. Even I put new lines by my hand my program cannot see it. When I want to print the character at the end of the line, it says it is a space (ascii = 32) and I am sur that I am end of the line. Here is my end of line control code, what can I do to fix it? And I read about a character called "carriage return (\r)" but it doesn't fix my problem either.
c = fgetc(fp);
printf("%d", c);
fseek(fp, -1, SEEK_SET);
if(c == '\n' || c == '\r')
fprintf(fp3, "%c%c", '\r', '\n');
If you are opening a text file and want newline conversions to take place, open the file in "r" mode instead of "rb"
FILE *fp = fopen(fname, "r");
this will open in text mode instead of binary mode, which is what you want for text files. On linux there won't appear to be a difference, but on windows, \r\n will be translated to \n
A possible solution it seems, is to read the numbers out of your file into an int variable directly.
int n;
fscanf(fp, "%d", &n);
unless the newline means something significant to you.
There are a couple of questions here
What is the difference between windows text newline and unix text newline?
UNIX newline is LF only. ASCII code 0x0a.
Windows newline is CR + LF. ASCII code 0x0d and 0x0a
Does your file have LF or CR ?
Use a hex editor to see the contents of the file. I use xxd on linux.
$ xxd unix.txt
0000000: 0a0a
$ xxd windows.txt
0000000: 0d0a

Carriage return in C doesn't work properly if the line contains spaces

I have a really weird problem with carriage return. I try to rewrite a line multiple times, it works fine if the line has no spaces and doesn't work if it has spaces. For instance this code
printf(" ");
printf("\rtest test");
printf(" ");
printf("\rtest test");
printf(" ");
printf("\rtest test");
printf(" ");
printf("\rtest test");
will type 4 lines "test test" while this code
printf(" ");
printf("\rtest");
printf(" ");
printf("\rtest");
printf(" ");
printf("\rtest");
printf(" ");
printf("\rtest");
will type a single line "test". What is the problem? I want to be able to rewrite any line disregard if it has spaces or not.
\r moves the cursor to the beginning of the physical line on the tty. If the previous print wraps the cursor to the next line (ie, the number of spaces + the number of characters in "text text" is larger than the width of the display), then the cursor is on the next physical line. You'll need to use more complex escape sequences to accomplish what you want. (ie, save/restore cursor position.) As an example (this is not portable, but works in many cases), you could do:
fputs( "\0337", stdout ); /* Save the cursor position */
printf( " ... " );
fputs( "\0338", stdout ); /* restore cursor position */
Note that if the cursor is at the bottom of the screen, this will probably not do exactly what you want. The position will be saved at the bottom of the screen, multiple lines of output will scroll, and the cursor will be restored to the bottom of the screen.
To print on a new line, use newline ('\n') not carriage-return.
The behaviour of '\r' on the console is to return to the start of the current line. In this case it is the large amount of space padding that was forcing a line wrap in the first instance.
In some cases a terminal can be configured to translate CR to CR+LF. Strictly '\n' is merely a LF character which moves down one line without returning to the start, but the normal behaviour for stdout is to translate that to CR+LF.

C Programming fprintf issue

I have a problem when writing a file on the text. As you could see, I used \n to put another set of my data on the next line. The problem is when i close the file and save again the data per line which ends with \n becomes \n\n and so on. That's why my file looks like this
FIRST SAVE
test, test, test
test, test, test
SECOND SAVE
test, test, test
test, test, test
THIRD SAVE
test, test, test
test, test, test
that's why when i display it on the screen... there are garbage value in between... My code is as follows:
save(){
int i = 0;
FILE *stream = NULL;
stream = fopen("student.txt", "wt");
printf("\nSaving the student list directory. Wait a moment please...");
printf("\nExiting the program...");
for (i=0; i<recordCtr; i++){
fprintf(stream, "%s, %s, %s\n", array[i]->studentID, array[i]->name, array[i]->course);
}
}
Help please... any suggestions will be appreciated. Thank you in advance.
Not sure of what you exactly do but if you parse back the file before saving it again probably you are forgetting to remove the old \n from the original last string..
EDIT: this is actually right. The OP uses fgetsfunction, which includes the line terminator.
So starting from "test, test, test\n" with strtok he will obtain "test" "test" "test\n" so that when it will be saved back a new newline (forget it) is added to the file.
You could fix it by setting last character to null with
linebuffer[strlen(linebuffer)-2] = '\0'
(it is safe since fgets return a null-terminated string by itself)
You can also add \n to delimiters used, you should end up with same behavior (not sure about empty tokens with strtok but IIRC they are just discarded).
I'm guessing this is on windows -- change your line:
stream = fopen("student.txt", "wt");
to:
stream = fopen("student.txt", "wb");
And you won't get extra \rs.
Alternatively, maybe the last of the strings you're fprintfing already has a newline at the end.
I'd guess that your array[i]->course field contains the \n previously written in the last save. Check the code that populates the array and make sure it is skipping newline characters.
Here:
fgets(linebuffer, 45, stream);
remove the trailing \n from linebuffer if there is one:
for (int i=strlen(linebuff)-1; i>=0 && linebuff[i]=='\n'; linebuff[i--]='\0');

Resources