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.
Related
My .txt file I have created before running the code looks like the following:
/*
I am Jason and I love horses hahaha/n
This is amazing, How much I love horses, I think I am in love/n
how many people love horses like I do?/n/n
this is quite a horsed up paragraph
*/
//I also manually wrote '\0' character at the end of my string//
And the output that I am wanting for this program is the same as above, and the code is the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *filepointer;
int buck;
int counter=1 ;
filepointer = fopen("inoutproj.txt","r");
while(buck=fgetc(filepointer),buck!=EOF)
{
if(buck=='\n')
{
++counter;
}
printf("%c",fgetc(filepointer));
}
printf("\nThere are %d lines in the text file\n\n",counter);
counter=1;
rewind(filepointer);
for(buck=fgetc(filepointer);buck<175;++buck)
{
if(fgetc(filepointer)=='\n')
{
++counter;
}
printf("%c",fgetc(filepointer));
}
printf("\nThere are %d lines in the text file\n",counter);
fclose(filepointer);
return 0;
the output is the following:
mJsnadIlv osshhh
Ti saaig o uhIlv oss hn mi oe o aypol oehre ieId?
hsi ut osdu aarp�
There are 3 lines in the text file
a ao n oehre aaa hsi mzn,Hwmc oehre,ItikIa nlv
hwmn epelv osslk o
ti sqieahre pprgah���������������
There are 3 lines in the text file
As you can see I tried two different approaches with fgetc (While loop and a for loop), but the output is still coming out broken. I have read some archived Macbook Pro document that the loops are reading the pushed back input from the input stream, and it seems to persistently do that for my code too (or maybe I am wrong).
Can someone tell me what is wrong with the code I have written and why my computer is not outputting the .txt file as I desire?
I am currently running Cygwin GCC on VSCode.
My system is a Macbook Pro 16in 2019
You are reading 2 characters for every one you print. The first character was read by "buck=fgetc(filepointer)" as an argument in the while statement. The second character was read by "printf("%c",fgetc(filepointer));".
So essentially your program first reads a character from the file and stores it in "buck", then reading another character and printing it out, resulting in the output missing characters.
You can do something like this:
FILE *filepointer;
int buck;
int counter=1 ;
filepointer = fopen("inoutproj.txt","r");
while(buck=fgetc(filepointer),buck!=EOF)
{
if(buck=='\n')
{
++counter;
}
printf("%c",buck);
}
printf("\nThere are %d lines in the text file\n\n",counter);
To simply print buck for every scan.
Good luck!
What #SSORshen says is correct, but you also have a similar problem in the for loop, following the rewind. But here you call fgetc three times per iteration, so you only print every third character. Also note that buck contains the character read, not a count. If you want to count how many characters are read, you'll need to use a separate counter variable, such as i below. Your second loop should look more like this:
counter=1;
rewind(filepointer);
for(int i=0;i<175;++i)
{
buck=fgetc(filepointer);
if(buck=='\n')
{
++counter;
}
printf("%c",buck);
}
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.
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 this simple C program that reads characters from the standard input and displays a table with numbered rows and columns inside which are the characters we wrote.
The code is:
#include <stdio.h>
#define COLS 6
#define WIDTH 5
int main(int argc, char *argv[]){
char buffer[COLS]={0};
int c;
int cols;
for(cols=0;cols<COLS && (c=getchar())!=EOF;cols++){
buffer[cols]=c;
}
if(cols!=0){
int a;
printf("%-*s",WIDTH,"");
for(a=0;a<cols;a++){
(cols!=(a+1)) ? printf("%-*d",WIDTH,(a+1)) : printf("%-*d\n",WIDTH,(a+1));
}
printf("%-*d",WIDTH,1);
for(a=0;a<cols;a++){
(cols!=(a+1)) ? printf("%-*c",WIDTH,buffer[a]) : printf("%-*c\n",WIDTH,buffer[a]);
}
cols=0;
int rows=2;
while((c=getchar())!=EOF){
if(cols==0){
printf("%-*d%-*c",WIDTH,rows,WIDTH,c);
cols++;
}
else{
if(COLS!=(cols+1)){
printf("%-*c%",WIDTH,c);
cols++;
}
else{
printf("%-*c\n",WIDTH,c);
cols=0;
rows++;
}
}
}
printf("End-Of-File\n");
}
else{
printf("No valid characters input\n");
}
return 0;
}
I compile the program with cc on Windows XP and if, in Windows console (cmd), I execute it with:
program.exe
then it reads the characters I input with the keyboard. It works fine.
The problem occurs when I decide that the characters are to be read from a txt file. So I create a txt file with notepad (in the same folder of program.exe) and I write a couple of sentences inside it. Then in console I execute:
program.exe<file.txt
but the output that I receive is "No valid characters input" as if the very first character read by the program was EOF.
Any ideas?
Thank you.
SOLUTION: I've just found out what the problem was. It was Comodo Internet Security that was preventing the program from reading characters from txt file. Actually Comodo was sandboxing the program. So after putting the program inside the "Safe Files" list everything worked like it should.
I hope this solution will help anyone with a similar problem.
SOLUTION: I've just found out what the problem was. It was Comodo Internet Security that was preventing the program from reading characters from txt file. Actually Comodo was sandboxing the program. So after putting the program inside the "Safe Files" list everything worked like it should.
I wrote the following code under MacOSX in XCode. When moving the code over to a Solaris Server three extra lines are being counted and I can not figure out why.
#include <stdio.h>
#define MAXLINE 281 // 281 is a prime number!!
char words[4][MAXLINE]; // words array to hold menu items
char displayfilename[4][MAXLINE]; //filename array to hold filename for display function
char exit_choice[4][MAXLINE]; //for user interaction and end of each function
int i; //standard array variable
int loop = 1; //control variable for my loop
int main()
{
printf("Enter filename: ");
scanf("%s", displayfilename[i]);
FILE *fp;
int clo_c , clo_nc, clo_nlines;
fp = fopen(*displayfilename,"r"); // open for reading */
if ( fp == NULL )
{
printf("Cannot open for reading!\n");
}
clo_c = getc( fp ) ;
while ( clo_c != EOF )
{
if (clo_c == '\n')
clo_nlines++ ;
clo_nc++ ;
clo_c = getc ( fp );
}
fclose( fp );
if ( clo_nc != 0 )
{
printf("There are %d lines in this file.\n", clo_nlines);
}
else
printf("File is empty, exiting!\n");
}
Can anyone explain to me Solaris is adding three to clo_nlines?
You didn't initialize clo_nlines - therefore you got 'undefined behavior'.
Declaring a variable in C doesn't set its value to anything - it just allocates some memory for that variable, and whatever junk happens to be in that bit (well, not bit, but you get the idea >.>) of memory is what the variable starts out as.
There are a couple of issues here.
First one, from a bulletproof-code point of view, is #Zilchonum's point, that clo_nc and clo_nlines aren't being initialized. In old C, that means you don't have any idea what's in them to start with and so don't have any idea what you'll end with.
However, later C standards define that uninitialized variables are set to 0, so that's probably not it unless you're setting the compiler to earlier behavior with flags.
More likely is Auri's point, that different machines use different newline standards. However, I believe that Mac OS/X uses a single character for newline, just as Solaris does.
Which brings us to the file itself. Try using oc -c to see what's actually in the file. my guess is that you'll find the file on one system is \r\n newlines, but on the other system has \n newlines, probably as a result of the settings of the file transfer program you used. It has probably converted to UNIX format on one but not the other.
Did you make sure you're not counting crlf as two linefeeds?