I am trying to write numbers from 1, up to 400 in a text file. I am using the code below, which is running without any errors, but the file is being left empty.
Any help would be appreciated.
#include <stdio.h>
int main(void)
{
FILE *filePointer;
filePointer = fopen("file.txt","w");
int i;
for(i=0; i > 400; i++)
{
fputs("%d, ",i,filePointer);
}
fclose(filePointer);
return(0);
}
No, there's no way that compiled without some serious-sounding warnings at least.
You're using fputs() as if it were fprintf(), passing it an integer instead of a FILE pointer (which the compiler should not allow) and an extra argument (which the compiler should not allow).
Also your for loop is broken. The middle part is an expression that should be true for as long as the loop should run, not the other way around.
You meant:
for(i = 0; i < 400; ++i)
{
fprintf(filePointer, "%d, ", i);
}
Also, you should check that the file really did open before assuming it did. I/O can fail.
Apart from the fputs() usage, the problem is:
for(i=0; i > 400; i++)
If you initialize a variable with zero and perform a loop as long as it's greater than 400, that won't last too long.
The fputs syntax seem wrong. I think it is:
int fputs(const char *str, FILE *stream)
Pick #unwind's approach (as mentioned above) but if you still want to use fputs then your fputs line should be expanded into 3 lines:
char temp[4]; // String to store 3-digit number + '\0'
sprintf(temp, "%d, ", i); // Prepare a string for a given number
fputs(temp, filePointer); // Write the string to the file
This should work. #happycoding :)
PS: You seem to be following a bit C++ standard in declaring a variable anywhere. It is not pure C. #justsaying
Related
I have the following code which reads from a given input file into and then into struct I have made.
OFFFile ReadOFFFile(OFFFile fileData, FILE* srcFile)
{
int nvert, nfaces;
fscanf(srcFile, "%s\n");
fscanf(srcFile, "%d %d %s\n", &nvert, &nfaces);
fileData.nvert = nvert;
fileData.nfaces = nfaces;
fileData.vertices = (int *) malloc(fileData.nvert * sizeof(float));
fileData.triFaces = (int *) malloc(fileData.nfaces * sizeof(int));
// Print to check correct size was allocated
printf("%d\n", (fileData.nvert * sizeof(float)));
printf("%d\n", (fileData.nfaces * sizeof(int)));
int i;
float ftemp1, ftemp2, ftemp3;
int itemp1, itemp2, itemp3;
fscanf(srcFile, "%f", &ftemp1);
printf("%lf", ftemp1);
fscanf(srcFile, "%f", &ftemp2);
// fscanf(srcFile, " %lf", &ftemp3);
/* for (i = 0; i < nvert; ++i)
{
fscanf(srcFile, "%f %f %f\n", &ftemp1, &ftemp2, &ftemp3);
fileData.vertices[i].x = ftemp1;
fileData.vertices[i].y = ftemp2;
fileData.vertices[i].z = ftemp3;
}
*/
return(fileData);
}
The problem I am having is with the whole last section that is currently in quotes (The 2 fscanf lines above it are me attempting to test). If I have just one float being read it works fine, but when I add the second or third the whole function fails to even run, although it still compiles. I believe it to be caused by the negative sign in the input, but I don't know how I can fix it.
The data is in the form
OFF
4000 7000 0
0.8267261981964111 -1.8508968353271484 0.6781123280525208
0.7865174412727356 -1.8490413427352905 0.7289819121360779
With the floats continuing on for 4000 lines (hence for loop). These are the structs I have made
typedef struct
{
float x;
float y;
float z;
} Point3D;
typedef struct
{
int face1;
int face2;
int face3;
} triFace;
typedef struct
{
int nvert;
int nfaces;
Point3D *vertices;
triFace *triFaces;
} OFFFile;
Text dump of another file with a lot less lines, also does not work in the for loop. Only using this for testing. https://justpaste.it/9ohcc
Your main problem is the first line in the readOFFFile function:
fscanf(srcFile, "%s\n");
This tries to read a string (presumably the string OFF on the first line of the file), but you don't give fscanf any place to store the string, so it crashes. (As an aside, your compiler really should have warned you about this problem. If it didn't, it's old-fashioned, and there are lots of easy mistakes that it's probably not going to warn you about, and learning C is going to be much harder than it ought to be. Or perhaps you just need to find an option flag or checkbox to enable more warnings.)
You can tell fscanf to read and discard something, without storing it anywhere, using the * modifier. Here's a modified version of your program, that works for me.
void ReadOFFFile(OFFFile *fileData, FILE* srcFile)
{
fscanf(srcFile, "%*s");
if(fscanf(srcFile, "%d %d %*s", &fileData->nvert, &fileData->nfaces) != 2) {
exit(1);
}
fileData->vertices = malloc(fileData->nvert * sizeof(Point3D));
fileData->triFaces = malloc(fileData->nfaces * sizeof(triFace));
int i;
for (i = 0; i < fileData->nvert; ++i)
{
if(fscanf(srcFile, "%f %f %f", &fileData->vertices[i].x,
&fileData->vertices[i].y,
&fileData->vertices[i].z) != 3) {
exit(1);
}
}
}
I have made a few other changes. The other fscanf call, that reads three values but only stores two, also needs a * modifier. I check the return value of fscanf to catch errors (via a crude exit) if the input is not as expected. I got rid of the \n characters in the fscanf calls, since they're not necessary, and potentially misleading. I got rid of some unnecessary temporary variables, and I had the readOFFFile function accept a pointer to an OFFFile structure to fill in, rather than passing and returning it.
Here is the main program I tested it with:
int main()
{
OFFFile fd;
FILE *fp = fopen("dat", "r");
ReadOFFFile(&fd, fp);
for (int i = 0; i < fd.nvert; ++i)
printf("%f %f %f\n", fd.vertices[i].x, fd.vertices[i].y, fd.vertices[i].z);
}
This is still an incomplete program: there are several more places where you need to check for errors (opening the file, calling malloc, etc.), and when you do detect an error, you need to at least print a useful error message before exiting or whatever.
One more thing. As I mentioned, those \n characters you had in the fscanf format strings were unnecessary and misleading. To illustrate what I mean, once you get the program working, have it try to read a data file like this:
OFF 2 0
0 0.8267261981964111
-1.8508968353271484 0.6781123280525208
0.7865174412727356 -1.8490413427352905 0.7289819121360779
Totally malformed, but the program reads it without complaint! This is one reason (one of several dozen reasons, actually) why the scanf family of functions is basically useless for most things. These functions claim to "scan formatted data", but their definition of "formatted" is quite loose, in that they actually read free-form input, generally without any regard for line boundaries.
For some advice on graduating beyond scanf and using better, more reliable methods for reading input, see this question. See also this section and this section in some online C programming course notes.
The line:
fscanf(srcFile, "%s\n");
is invoking undefined behavior. The compiler should warn you about that. Once you've invoked UB, there's no point in speculating further about what is happening.
It's not clear to me what you intended that line to do, but if you use %s in a scanf, you need to give it a valid place to write data. You should always check the value returned by scanf to ensure that you have actually read some data, and you should never use "%s" without a width modifier. Perhaps you want something like:
char buf[256];
if( fscanf(srcFile, "%255s ", buf) == 1 ){
/* Do something with the string in buf */
}
From your comment, it seems that you are intending to use that scanf to skip a line. I strongly recommend using a while(fgetc) loop instead of scanf to do that. If you do want to use scanf, you could try something like fscanf(srcFile, "%*s\n"), but beware that it will stop at the first whitespace, and not necessarily consume an entire line. You could also do fscanf(srcFile, "%*[^\n]%*c"); to consume the line, but you are really better off using a fgetc in a while loop.
Addressing title question:
"How do I read multiple floats from one line of a file"
...with suggestions for a non-scanf() approach.
Assuming the file is opened, (and a file pointer) fp is obtained ) , the first two lines are already handled, and values into ints, say the lines value is converted to int lines;
And given your struct definition (modified to use double to accommodate type compatibility in code below):
typedef struct
{
double x;
double y;
double z;
} Point3D;
In a function somewhere here is one way to parse the contents of each data line into the 3 respective struct values using fgets(), strtok() and strtod():
char delim[] = " \n";
char *tok = NULL;
char newLine[100] = {0};
Point3D *point = calloc(lines, sizeof(*point));
if(point)
{
int i = 0;
while(fgets(newLine, sizeof newLine, fp))
{
tok = strtok(newLine, delim);
if(tok)
{
if(parseDbl(tok, &point[i].x))
{
tok = strtok(NULL, delim);
if(tok)
{
if(parseDbl(tok, &point[i].y))
{
tok = strtok(NULL, delim);
if(tok)
{
if(!parseDbl(tok, &point[i].z))
{
;//handle error
}else ;//continue
}else ;//handle error
}else ;//handle error
}else ;//handle error
}else ;//handle error
}else ;//handle error
i++;//increment for next read
}//end of while
}else ;//handle error
Where parseDbl is defined as:
bool parseDbl(const char *str, double *val)
{
char *temp = NULL;
bool rc = true;
errno = 0;
*val = strtod(str, &temp);
if (temp == str)
rc = false;
return rc;
}
Its my first question, so I hope you guys can help. In class, I was tasked with writing a C code that reads a group of strings from 1 file, and print them in another file, along with the ASCII codes of each character in the string, and the sum of the ASCII code values. The code below compiled, but did not execute. Is the code right, but I did something wrong, or is the code simply wrong. Thanks a bunch.
Note: the first file reads from a text file named list, and the code prints into a text document named list2.
#include <stdio.h>
int main(void)
{
FILE *file1, *file2;
file1 = fopen("list.txt", "r");
if (file1==NULL)
{
puts(" File not exisiting\n");
}
file2 = fopen("list2.txt", "w");
if (file2==NULL)
{
puts(" File could not open \n");
}
char a[5];
fscanf(file1, "%s", a);
int b,c;
while (a[5]!=EOF)
{
for (int i=0;i<5;i++)
{
fprintf(file2, "%c", a[i]);
b=a[i];
fprintf(file2, "%d", b);
c+=b;
}
}
fprintf(file2, "%d", c);
return 0;
}
Point 1. With a definition like
char a[5];
using
while (a[5]!=EOF)
invokes undefined behaviour.
You're facing off-by-one error. Remember, array index in c starts from 0. The valid access it at most upto a[4].
Point 2. fscanf(file1, "%s", a); is unsafe. It can cause buffer overflow. Atleast, you need to write
if ( fscanf(file1, "%4s", a) != 1)
{
//scanning not successful, take necessary measures
}
//otherwise, continue nomal execution.
Point 3. The logic for while loop is not correct. You don't have a break condition there.
Point 4. c+=b;, here c is used uninitalized. read-before-write scenario. Again, undefined behaviour. Remember, auto local variables doesnot get initialized to 0 or some value automatically. You've to initialize explicitly.
Point 5. Do not continue normal execution if if (file1==NULL) condition satisfies. Only printing a message is not sufficient. You should discontinue the program and avoid using file1, file1 etc.
Credits for point 5: user4402433
Include return in the file check as
if (file1==NULL)
{
puts(" File not exisiting\n");
return 0;
}
as there is no use of proceeding with the code if any one of the file is opened.
Also initialize the value of c=0; before while so that any garbage value can be avoided.
The array a[] has to be indexed to update the file content. So place the
fscanf(file1, "%s", a[i]);
inside the for() loop . This is to avoid buffer overflow which occurs in rare cases.
I'm not familiar with C at all. I just need to input my data into an already well-developed model in C, put the data in arrays, get my output and put that output back into my program in Python. My data is in a CSV file and I'm just trying to put it in a 2-D array to run through some functions. When I run the following code to make sure I created my array, I get a random single value in the output that does not match the original data at all. Sometimes it prints 0.00000. I'm trying to view the entire array to make sure it's ready to be input.
Also, this is just a sample; my real data set will have >3000 rows. I understand I will need to use malloc() for this when I run my real data, correct?
#user3629249 thank you and #Cool Guy for all your comments. Here's what I have now. I think sprintf() is still having trouble converting my array values back to a float. I've searched all over and I still cant tell what I doing wrong but the error is telling me that data[l][k] and todata are still incompatible, could you tell me if I'm on the right track and what I'm doing wrong with the sprintf() function?
#include <stdio.h>
int main() {
FILE *fp;
fp=fopen("airvariablesSend.csv", "r");
if(fp == NULL){
printf("cannot open file\n\n");
return -1;
}
// Headers removed for simplicity. Still found in airvariables.csv to see which //column means what
float data[9][6]; //for putting into array
int k , l;
float num; //for using getline() function
char *memory;
int nbytes = 500;
// space for using malloc? Is this enough or too much?
char *token; //for parsing through line using strtok()
char *search = ","; //delimiter for csv
char *todata; //for
//asking for space on heap
memory = (char *) malloc (nbytes + 1);
// Don;t need to use realloc() because getline() does it automatically? //http://crasseux.com/books/ctutorial/getline.html
for(k = 0; k < 6 ; k++) //repeats for max number of columns
{
for (l=0; l< 9; l++) //modify for number of rows that you have
{
num = getline (&memory, &nbytes, fp); //reading line by line
token = strtok(num, search); //separating lines by comma in csv
//Apparently strtok() will only use whitespace and I'm getting warnings here too. Is there another function for separating by commas?
sprintf(todata, "%f", token);
data[l][k] = todata;
printf("%f\n", data[l][k]);
}
}
fclose(fp);
free(memory);
return 0;
}
Change
for (l=1; l< 11; l++)
To
for (l=0; l< 10; l++)
And
printf("%f\n", data[10][7]);
To
printf("%f\n", data[l][k]);
And move the printf just after
data[l][k] = num;
The former is done because array indices start from 0 and end at length-1.
The latter is done because you need to loop through the array to get each value that is stored in each index of the array and print it. You can't just use data[10][7] and expect the whole array to be printed. data[10][7] is an invalid location and accessing it invokes Undefined Behavior which means that anything can happen including segmentation faults, runtime errors, crashes etc.
Also, add a return -1; in the end of the body of the first if to end the execution of the program if the fopen failed to open its first argument.
in my project I used arrays not pointers. My purpose is here copy all characters one-by-one from text.file into array. I found some examples from the Internet, this site but none of them was useful for me.
Think that input1.txt is "abcd" I want like these input1[0] = a, input1[1] = b, etc.
main ()
{
FILE *f1 = fopen("input1.txt", "r");
int i;
fseek(f1, 0, SEEK_END);
int inputsize = ftell(f1); //its about text's size
char input1[inputsize];
for(i = 0; i < inputsize; i++)
{
fscanf(f1, "%c", &input1[i]);
}
printf("%c ", input1[3]);
getchar();
}
When I run this code it doesn't print "d", but prints "6". Why is this happening? What should I do? Thanks for help
You seek to the end of the file to obtain it's size, but don't seek back to the start of the file again before you start actually reading it.
Insert just before your loop:
fseek(f1,0,SEEK_SET);
Pasting your code into my compiler with this amendment worked on my machine
You could also use a function rewind(FILE*) instead of doing an fseek() again.
Worth noting should be the fact that you're allocating an array with a variable, which might be a bad idea in this case (especially when you could be reading a bigger file than one with 4 characters).
Im currently learning C through random maths questions and have hit a wall. Im trying to read in 1000 digits to an array. But without specifiying the size of an array first i cant do that.
My Answer was to count how many integers there are in the file then set that as the size of the array.
However my program returns 4200396 instead of 1000 like i hoped.
Not sure whats going on.
my code: EDIT
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
FILE* fp;
const char filename[] = "test.txt";
char ch;
int count = 0;
fp = fopen(filename, "r");
if( fp == NULL )
{
printf( "Cannot open file: %s\n", filename);
exit(8);
}
do
{
ch = fgetc (fp);
count++;
}while (ch != EOF);
fclose(fp);
printf("Text file contains: %d\n", count);
return EXIT_SUCCESS;
}
test.txt file:
731671765313306249192251196744265747423553491949349698352031277450632623957831801698480186947885184385861560789112949495459501737958331952853208805511
125406987471585238630507156932909632952274430435576689664895044524452316173185640309871112172238311362229893423380308135336276614282806444486645238749
303589072962904915604407723907138105158593079608667017242712188399879790879227492190169972088809377665727333001053367881220235421809751254540594752243
525849077116705560136048395864467063244157221553975369781797784617406495514929086256932197846862248283972241375657056057490261407972968652414535100474
821663704844031998900088952434506585412275886668811642717147992444292823086346567481391912316282458617866458359124566529476545682848912883142607690042
242190226710556263211111093705442175069416589604080719840385096245544436298123098787992724428490918884580156166097919133875499200524063689912560717606
0588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
Any help would be great.
You forgot to initialize count, so it contains random garbage.
int count = 0;
(But note that with this change it's still not going to work, since %d in a scanf format means read as many digits as you find rather than read a single digit.)
Turn on your compiler's warnings (-Wall), it will tell you that you didn't initialize count, which is a problem: it could contain absolutely anything when your program starts.
So initialize it:
int count = 0;
The other problem is that the scanfs won't do what you want, at all. %d will match a series of digits (a number), not an individual digit. If you do want to do your counting like that, use %c to read individual characters.
Another approach typically used (as long as you know the file isn't being updated) is to use fseek/ftell to seek to the end of the file, get the position (wich will tell you its size), then seek back to the start.
The fastest approach though would be to use stat or fstat to get the file size information from the filesystem.
If you want number of digits thin you tave to do it char-by-char e.g:
while (isdigit(fgetc(file_decriptor))
count++;
Look up fgetc, getc and scanf in manpages, you don't seem to understand whats going on in your code.
The way C initializes values is not specified. Most of the time it's garbage. Your count variable it's not initialized, so it mostly have a huge value like 1243435, try int count = 0.