Here's my code:
#include <stdio.h>
#include <stdlib.h>
main(){
FILE* fp = fopen("img.ppm","w");
fprintf(fp,"%c", 10);
fclose(fp);
return 0;
}
for some reason that I am unable to uncover, this writes 2 bytes to the file: "0x0D 0x0A" while the behaviour I would expect is for it to just write "0x0A" which is 10 in decimal. It seems to work fine with every single other value between 0 and 255 included, it just writes one byte to the file. I am completely lost, any help?
Assuming you are using the Windows C runtime library, newline characters are written as \r\n, or 13 10. Which is 0x0D 0x0A. This is the only character that's actually written as two characters (by software compiled using the Windows toolchain).
You need to open the file with fopen("img.ppm","wb") to write binary.
Related
I am trying to read from a file and for some reason sometimes it works and sometimes I get the most bizarre results ever.
The code:
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
FILE *f = fopen("mac_input_off.txt","r");
char c[2] = "";
while ( 0 != fread(c,sizeof(char),1,f) )
{
c[1] = '\0';
printf("%s",c);
}
fclose(f);
}
In windows, visual studio 2013 it works just fine, but in ubuntu linux, on vmware, for some reason it refuses to read the text and reads only the carriage return at the end of the text(encoded with mac os newlines).
This is the text in the file: bbb58bc7a385cf89ee2102d5ea8d7cab.
A possible reason is that the 8th bit in every byte is set to 0 in this text.
Any idea what am I not getting?
EDIT: The funny semi-colon terminating the while loop was removed and yet nothing is fixed... back to the drawing board.
Tried to check if it actually reads things by putting a breakpoint after the 10th line in gdb (my actual knowledge of gdb is meager and I can't seem to get any front-end working) and it does in fact read the characters. It just doesn't want to print them.
Note that in the line:
while ( 0 != fread(c,sizeof(char),1,f) );
there is no loop body because the statement is terminated with a semi-colon.
Remove the ; and the statements enclosed in the following {...} will be executed as the body of the loop. You should then see the contents of the file displayed.
I have a basic C program that reads some lines from a text file containing hundreds of lines in its working directory. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
#include <unistd.h>
int main(int argc, const char * argv[]) {
srand((unsigned)time(0));
char *nameFileName = "MaleNames.txt";
wchar_t line[100];
wchar_t **nameLines = malloc(sizeof(wchar_t*) * 2000);
int numNameLines = 0;
FILE *nameFile = fopen(nameFileName, "r");
while (fgetws(line, 100, nameFile) != NULL) {
nameLines[numNameLines] = malloc(sizeof(wchar_t) * 100);
wcsncpy(nameLines[numNameLines], line, 100);
numNameLines++;
}
fclose(nameFile);
wchar_t *name = nameLines[rand() % numNameLines];
name[wcslen(name) - 1] = '\0';
wprintf(L"%ls", name);
int i;
for (i = 0; i < numNameLines; i++) {
free(nameLines[i]);
}
free(nameLines);
return 0;
}
It basically reads my text file (defined as a macro, it exists at the working directory) line by line. Rest is irrelevant. It runs perfect and as expected on my Mac (with llvm/Xcode). When I try to compile (nothing fancy, again, gcc main.c) and run it on a Linux server, it either:
Exists with error code 2 (meaning no lines are read).
Reads only first 3 lines from my file with hundreds of lines.
What causes this indeterministic (and incorrect) behavior? I've tried commenting out the first line (random seed) and compile again, it always exits with return code 2.
What is the relation between the random methods and reading a file, and why I'm getting this behavior?
UPDATE: I've fixed malloc to sizeof(wchar_t) * 100 from sizeof(wchar_t) * 50. It didn't change anything. My lines are about 15 characters at most, and there are much less than 2000 lines (it is guaranteed).
UPDATE 2:
I've compiled with -Wall, no issues.
I've compiled with -Werror, no issues.
I've run valgrind didn't find any leaks too.
I've debugged with gdb, it just doesn't enter the while loop (fgetws call returns 0).
UPDATE 3: I'm getting a floating point exception on Linux, as numNameLines is zero.
UPDATE 4: I verify that I have read permissions on MaleNames.txt.
UPDATE 5: I've found that accented, non-English characters (e.g. Â) cause problems while reading lines. fgetws halts on them. I've tried setting locale (both setlocale(LC_ALL, "en.UTF-8"); and setlocale(LC_ALL, "tr.UTF-8"); separately) but didn't work.
fgetws() is attempting to read up to 100 wide characters. The malloc() call in the loop allocates 50 wide characters.
The wcscpy() call copies all the wide characters read. If more than 50 wide characters have been read (including the terminating nul) then wcscpy() will overrun the allocated buffer. That results in undefined behaviour.
Instead of multiplying by 50 in the loop, multiply by 100. Or, better yet, compute the length of string read and use that.
Independently of the above, your code will also overrun a buffer if the file contains more than 2000 lines. Your loop needs to check for that.
A number of the functions in your code can fail, and will return a value to indicate that. Your code is not checking for any such failures.
Your code running under OS X is happenstance. The behaviour is undefined, which means there is potential to fail on any host system, when built with any compiler. Appearing to run correctly on one system, and failing on another system, is actually a valid set of responses to undefined behaviour.
Found the solution. It was all about the locale, from the beginning. After experimenting and hours of research, I've stumbled upon this: http://cboard.cprogramming.com/c-programming/142780-arrays-accented-characters.html#post1066035
#include < locale.h >
setlocale(LC_ALL, "");
Setting locale to empty string solved my problem instantly.
I have a file named output.txt and i want to print in a root (√) symbol in it.
Here is my program
#include<stdio.h>
#include<conio.h>
void main(void)
{
FILE *fptr;
fptr = fopen("output.txt","w+"); //open the file to write
fprintf(fptr,"\xfb"); // \xfb is the hexadecimal code for root symbol
fclose(fptr);
}
but when i run the program (û) is printed in it
The problem you are encountering is because you are attempting to use part of the extended ASCII set (ie: characters above 127 in value). The code page is something you set so that if the MSB of an 8-bit ASCII symbol is set, it can map to one of many different code pages depending on region/locale, OS, etc (ie: Greek, Latin, etc). In most cases, ASCII characters are generally considered to be 7-bit, ignoring the code page enable bit.
Attempting to use extended ASCII is not a portable approach, so your best alternative is to:
Make use of unicode
Make sure your C compiler is C99 compliant.
The following example resolves the original problem.
Source Code
#include <stdio.h>
void main(void) {
FILE *fptr;
fptr = fopen("output.txt","w+"); //open the file to write
fprintf(fptr, "\u221A\n");
fclose(fptr);
}
Output from Sample Run
√
References
How to print Extended ASCII characters 127 to 160 in through a C program?, Accessed 2014-04-16, <https://stackoverflow.com/questions/16359225/how-to-print-extended-ascii-characters-127-to-160-in-through-a-c-program>
Unicode Character 'SQUARE ROOT' (U+221A), Accessed 2014-04-16, <http://www.fileformat.info/info/unicode/char/221a/index.htm>
I'm having strange results doing a simple open and write. I'll quote the program and then i'll explain my results:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(){
int fd = open("hello.txt", O_WRONLY|O_CREAT, 0700);
char buf[] = "Hello world\n";
int i=0;
for(i = 0; i < 10;i++){
write(1,buf,sizeof(buf));
write(fd, buf, sizeof(buf));
}
close(fd);
return 0;
}
Using this code, the output in the terminal will be Hello world ten times as expected... But on the file hello.txt I get this:
效汬潷汲䠀汥潬眠牯摬
效汬潷汲䠀汥潬眠牯摬
效汬潷汲䠀汥潬眠牯摬
效汬潷汲䠀汥潬眠牯摬
效汬潷汲䠀汥潬眠牯摬
1)Why does this happens? What did I do wrong? And why chinese?
Thanks in advance
Edit: Compiling using gcc 4.8.1 with -Wall flag: no warnings
You are writing 13 characters (sizeof(buf), which includes the terminating 0.
Because you are sending a literal 0 to your terminal, it probably assumes your text is 'binary' (at least, that is what OS X's Terminal warns me for), and hence it attempts to convert the text to a likely encoding: Unicode 16 bit. This is 'likely', because in Latin text, lots of characters have a 0 in their 16-bit code.
If you check the Unicode values of these Chinese characters, you will find
效 = U+6548
汬 = U+6C6C
潷 = U+6F77
汲 = U+6C72
which seem to contain the hex codes for the 8-bit characters you wanted. I suspect the space U+0020 is missing in this list because your terminal refuses to show "invalid" Unicode characters.
Forgot to add the obvious solution: write out one character less. Or, more obvious, write out strlen(buf) characters.
I am working on TTCN-3 (Testing and Test Control Notation) scripting language. I wanted to prepare on guideline checker for this code files.
For that I want to read lines of TTCN-3 script file( some thing like file.ttcn ) one by one into a buffer. But for me fopen / sopen / open / fgetc / fscanf are not able to work properly and are not reading the file correctly. It is giving NULL. Is there any way I can read characters of it into a buffer. I think C cannot read files with more than three extension characters (like .ttcn). Forgive me if my assumption is wrong.
My Environment is Turbo C on windows.
Edit:
Yes I checked those errors also but they are giving unknown error for read()
and no such file or directory exists.
My code is as follows
#include <errno.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <process.h>
#include <share.h>
#include <stdio.h>
int main(void)
{
int handle;
int status;
int i=0;
char ch;
FILE *fp;
char *buffer;
char *buf;
clrscr();
handle = sopen("c:\\tc\\bin\\hi.ttcn", O_BINARY, SH_DENYNONE, S_IREAD);
/here even I used O_TEXT and others/
if (!handle)
{
printf("sopen failed\n");
// exit(1);
}
printf("\nObtained string %s #",buf);
close(handle);
fp=fopen("c:\\tc\\bin\\hi.ttcn","r"); \\sorry for the old version of one slash
if(fp==NULL) \\I was doing it with argv[1] for opening
{ \\user given file name
printf("\nCannot open file");
}
ch=fgetc(fp);
i=0;
while(i<10)
{
printf("\ncharacter is %c %d",ch,ch);
i++; //Here I wanted to take characters into
ch=fgetc(fp); //buffer
}
getch();
return 0;
}
The most likely culprit is your Turbo C, an ancient compiler. It's techincally a DOS compiler, not Windows. That would limit it's RunTme Library to 8.3 filenames. Upgrade to something newer - Turbo C++ seems like a logical successor, but Microsoft's VC++ Express would work as well.
Your assumption is wrong about extensions. If fopen is returning NULL, you should output the result of strerror(errno) or use the perror() function to see why it failed.
Edit: The problem is probably because you have "c:\tc\bin\hi.ttcn". in C, "\t" is interpreted as tab, for example.
You could do
"c:\\tc\\bin\\hi.ttcn"
But this is extremely ugly, and your system should accept:
"c:/tc/bin/hi.ttcn"
MS-DOS does not know about long file names, thos including files with extensions longer than 3 characters. Therefore, the CRT provided by Turbo C most probably does not look for the name you are providing, but a truncated one - or something else.
Windows conveniently provides a short (i.e. matching the 8.3 format, most of the time ending in ~1 unless you play with files having the same 8-character prefix) file name for those; one way to discover it is to open a console window and to run "dir /x" in the folder your file is stored.
Find the short name associated to your file and patch it into your C source file.
Edit: Darn, I'll read the comments next time. All credits to j_random_hacker.
Now that you've posted the code, another problem comes to light.
The following line:
fp=fopen("c:\tc\bin\hi.ttcn","r");
Should instead read:
fp=fopen("c:\\tc\\bin\\hi.ttcn","r");
In C strings, the backslash (\) is an escape character that is used to encode special characters (e.g. \n represents a newline character, \t a tab character). To actually use a literal backslash, you need to double it. As it stands, the compiler is actually trying to open a file named "C:<tab>c<backspace>in\hi.ttcn" -- needless to say, no such file exists!