C program won't get access to textile - c

Just to make it clear - I'm a beginner in C.
When my program is running (using Xcode), no values correspond to the values in "resultfortran.txt". Instead, they become very small, very large or zero (looks random). For example, the variable n becomes 0, even though the first line in "resultfortran.txt" is 10. The variables min and max also becomes very small (and don't get the values at line 2 and 3).
I have searched the web all day, and asked my fellow students. If it is of interest, I got the error "EXC_BAD_ACCESS" on the line where the file is opened, but that error has (some how?) disappeared. And yes, "resultfortran.txt2 is in the same folder as main.m.
The start of the program is shown below:
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GLUT/glut.h>
#include <OpenGL/OpenGL.h>
#include <Cocoa/Cocoa.h>
static void draw( void )
{
int n,i,j;
float step,min,max,x,y,scaled;
float matrix[1000][1000];
FILE *fp; //reads input file
fp=fopen("resultfortran.txt", "r");
fscanf(fp,"%d",&n); //Gives n the value of the first line.
step=(1.0/n); //Defines step size
fscanf(fp,"%f",&min); //Gives min the value of the second line.
fscanf(fp,"%f",&max); //Gives max the value of the third line.
for (i=0;i<n+1;i=i+1)
{
for (j=0;j<n+1;j=j+1)
{
fscanf(fp,"%f",&matrix[i][j]);
}
}
... not finished here ...
The first lines of the file "resultfortran.txt" (which is a output from a fortran script) is shown below:
10
0.00000000
0.500000000
0.0000000000
0.0025000002
0.0100000007
0.0225000009
0.0400000028
0.0625000000
0.0900000036
0.1224999949
0.1600000113
0.2024999857
0.2500000000
0.0025000002
0.0050000008
0.0125000002

Since you're "a beginner in C", I want to first welcome you to what is a very rigorous but rewarding language. Though, to be fair, I wouldn't consider someone who is writing operating system code to be a "beginner" in C.
I'll gladly assist you and update this answer as we proceed. My first suggestion is as follows:
The first thing you always should do when doing file operations (like opening one) is to check the results of the execution! For example, if you read the man page on fopen(), you'll see that fopen() will
return a FILE pointer. Otherwise, NULL is returned and errno is set to
indicate the error.
So, use something similar to the code below to make sure that your file is opening as expected:
if (fp == NULL) {
printf("fopen did not work! Check errno %d\n", errno);
}
else {
printf("fopen workd!\n");
}
I will update this answer once you get back to me on the results of implementing the code above.

Related

Inexplicable "Invalid Argument" error from fopen_s

In essence I have come across an issue while working on a project to send files over a socket. I'm a bit of a newbie, and after a few hours of searching I still haven't found a working solution, but I have boiled down the problem into the following code.
#include <stdio.h>
#include <errno.h>
#include <Windows.h>
int main()
{
const char* fileName = "‪C:\\Users\\Username\\Desktop\\bugs.jpg";
FILE* f;
fopen_s(&f, fileName, "r");
if (f == NULL)
printf("Null Result");
else
printf("Working");
printf("\nError %d \n", errno);
}
For some reason the program is unable to open the file, and errno returns a value of 22, which corresponds to EINVAL, or invalid argument here. I am very confused as it appears that I am providing fopen_s with the correct arguments according to its specification. Any help or pointers(haha) is greatly appriciated, thanks!
Thanks to the comments I found out why it wasn't working. Essentially, I was copying the "Object Name" field from the file properties to save time typing it out. Somehow this drags along an invisible '\u202A' character which completely breaks fopen_s.
Picture
In a nutshell, don't try and cut corners.

File path as user input in C

I couldnt find specific answer to my question. I am really low level, just started and had a class in which I learned to create file from the CodeBlocks. Took code with me home but it wont work because its not on the same computer. So, the idea was to make something that will allow user to choose path for the newly formed .txt file. When, instead of s, I manually insert "c:\example.txt" or something like that, the code creates a file "example.txt" but when I send it as input it simply wont. Why?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *a=NULL;
char s[50];
puts("Enter the path of the file: ");
fgets(s,50,stdin);
a=fopen(s,"w");
if(a==NULL)
exit(1);
else
printf("Successful input");
}
So the entire problem was the fgets function which adds the \nat the end? Is there any other idea to make this work?
You can replace the
fgets(s,50,stdin);
with
scanf("%49[^\n]%*c", s);
- this reads input excluding the \n into s, as long as its size allows, and consumes the \n, so that it doesn't get into the way of possible later input.

fgetws can't read non-English characters on Linux

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.

Reading from files

Yesterday in my class we started working with files for the first time. I wanted to see how it works, so I made a program where I write a word and that word has to be written in a certain file(that part worked). After that, I wanted to read from that file a number of characters and show it on the screen.
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <sys/stat.h>
#include <process.h>
#include <fcntl.h>
#include <string.h>
int main()
{
int df,m;
char c[50],d[50];
printf("c= \n");
gets(c);
m=strlen(c);
df=open("e:\\codeblocks\\fisperimente\\text2.txt",O_RDONLY|O_WRONLY);
if (df==-1) {printf("error");exit(1);}
write(df,c,m);
/*int i,n;
n=read(df,d,5);
for (i=1;i<=n;i++)
{
printf("%c",d[i]);
} */
close(df);
return 0;
}
What I put in my commentary is the part that doesn`t work. I noticed that if I printf n, it returns -1, which means that I did something wrong while reading from the file.
First, I would avoid gets() at all costs. It is unsafe, and is considered deprecated. It may be removed in the future. Instead, consider using fgets(), like so:
fgets(c, sizeof(c), stdin);
Next, your open is suspicious:
df=open("e:\\codeblocks\\fisperimente\\text2.txt",O_RDONLY|O_WRONLY);
Read only and write only are mutually exclusive. If you want to open a file for both read and write, you need O_RDWR.
And finally, after you write to your file, the file pointer points to the end of file. If you want to reread it, you need to seek back to the beginning. This will do that:
lseek(df, 0, SEEK_SET);
Once you do that, you can read your file back in.
You need to seek to the beginning of the file, to read it's contents back. Or you can just close it or open it again for reading.
Try use flag O_RDWR, the or'd result of read only and write only flags is not what you think it does ;)
Note that mode O_RDWR is not usually equal to O_RDONLY | O_WRONLY. Therefore, you probably opened the file with O_WRONLY (classically, O_RDONLY is 0). This is not yet your major problem; it will become one.

basic file input using C

So im working on learning how to do file I/O, but the book I'm using is terrible at teaching how to receive input from a file. Below is is their example of how to receive input from a file, but it doesn't work. I have copied it word for word, and it should loop through a list of names until it reaches the end of the file( or so they say in the book), but it doesn't. In fact if I leave the while loop in there, it doesn't print anything.
#include <stdio.h>
#include <conio.h>
#define MAX 250
int main()
{
char name[MAX];
FILE*pRead;
pRead=fopen("test.txt", "r");
if (pRead==NULL)
{
printf("file cannot be opened");
}else
printf("contents of test.txt");
while(fgets(name,sizeof(name),pRead)!=NULL){
{
printf("%s\n",name);
fscanf(pRead, "%s", name);
}
getch();
}
Even online, every beginners tutorial I see does some variation of this, but I can't seem to get it to work even a little bit.
I believe your array is too small and therefore when you are reading fscanf overwrites memory causing bizarre behavior
If you just want to read the file - presuming now there is one name per line followed by newline in the input file - just read the file using fgets() instead.
#define MAXLINE 256
char name[MAXLINE];
while (fgets(name,sizeof(name),pRead)!=NULL)
{
// do whatever
}

Resources