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.
Related
I need to write a simple program that reads numbers from a file, then stores those numbers in an array. The last number in the file is 0 so the program knows when to reading.
When I execute the program, Dec C++ crashes. I went online for solutions and changed the settings accordingly but that didn't work. I ran other programs I have and it works fine, which makes me think there's something wrong with the code.
Any ideas?
#include <stdio.h>
int main(){
int i, j=0, k;
int values[20];
FILE*ptr;
ptr = fopen("input.txt", "r");
fscanf(ptr, "%d", &i);
while (i=!0){
values[j]=i;
j++;
fscanf(ptr, "%d", &i);
}
for (k=0; k<20; k++)
printf("%d\n", values[k]);
fclose (ptr);
return 0;
}
Another typo:
while (i=!0){
should be:
while (i != 0){
Your code was assigning !0 to i, instead of comparing i with 0. !0 is 1, so you had an infinite loop, and you were writing beyond the bounds of the array.
Also note that if the file has more than 20 numbers in it, you'll write outside the array. And if it has fewer than 20 numbers, the loop that prints values[k] will read uninitialized array entries.
There are a couple of things that are wrong with the code:
You are not checking for error after opening input.txt
While i=!0 is syntactically correct it probably does not do what you want !0 is 1, so it is the same as i=1, you are putting value 1 into i
To help you with debugging:
add printf() statements to your code to verify that you reached a certain line and to check the values of the variables
learn to use a debugger
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
I want read text file and store in array then show.
This is my code:
int i = 0, line = 5;
char ch[100];
FILE *myfile;
myfile = fopen("test.txt","r");
if (myfile== NULL)
{
printf("can not open file \n");
return 1;
}
while(line--){
fscanf(myfile,"%s",&ch[i]);
i++;
printf("\n%s", &ch[i]);
}
fclose(myfile);
return 0;
}
This is my text:
test 123562
856
59986
But result:
est
2356
56
9986
What is wrong? :(
ch[i] is holding a single character. Statement fscanf(myfile,"%s",&ch[i]); will scan string to ch[i] which can hold only one character. There is no place for '\0' which leads your program to undefined behavior.
Change
fscanf(myfile,"%s",&ch[i]);
to
fscanf(myfile,"%s",ch);
Previous answer was wrong. Behavior of program is well defined but you are scanning the file in a wrong manner. Your program will work as expected if you place i++; after printf statement.
while(line--){
fscanf(myfile,"%s",&ch[i]);
printf("\n%s", &ch[i]);
i++;
}
The reason is that &ch[i] is a pointer to the ith element of the array and string will be stored in array starting at position i. For the input given, this will work because the given array is large enough to hold the string.
You can do this as:
while(line--){
fscanf(myfile,"%s",ch);
printf("\n%s", ch);
i++;
}
but it will overwrite the array ch each time a string is scanned to it. Better to use a two dimensional array to store strings and read file with fgets.
You're not going to be able to fit five lines in the single char ch[100] array; that's just an array of 100 characters.
You can make it an array of arrays, i.e. char ln[5][100] which will give you room for five lines of 100 characters each.
Then you of course need to index into that array in the loop, i.e.:
for(int i = 0; i < 5; ++i)
{
if(fgets(ln[i], sizeof ln[i], myfile) == NULL)
{
fprintf(stderr, "Read error on line %d\n", i);
exit(1);
}
}
This uses fgets() which is much better suited at reading in whole lines; fscanf() will stop at whitespace with %s which is seldom what you want.
There is no need to use the ampersand in the scanf while getting the string. Make that into like this.
fscanf(myfile,"%s",&ch[i]);
to
fscanf(myfile,"%s",ch);
&ch[i] It will get the character for i th position in that array. If you want to get like that you can use the %c instead of %s. And change this one to.
printf("\n%s", ch);
While printing the string when you use the ampersand(&) that will access the address of that variable.
The program developed must be able to read the input files containing matrix A and matrix B
using fopen function
a. Matrix A and B of different size may be stored in different input file (if required).
Scan and assign matrix A and B as array using fscanf function and for loop
Perform matrix operations
a. Add matrix A and B
b. Subtract matrix A and B
c. Multiply matrix A and B
Use conditional statement if or switch for switching between 3, 4 and 5 elements matrix.
Print all input matrices and results obtained in a new file called output.dat using fprintf
function.
The output.dat file must have a header with the following information:
a. Student name
b. Student matric number
c. Class section
d. Lecturer name
e. Project title
Below the header, the output file must contain matrix A and B and the results from matrix
operation.
Use matrix A and B as given below:
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.
I have the following in a text file called: values.txt
1 4
2.5 3.76
122 10
277.543
165.4432
I am trying to read the content of this text file, and add each two pairs together and output the result ...
the output would be something like this :
1 Pair:(1, 4) = 5
2 Pair:(2.5, 3.76)= 6.26
and so on ..
I am opening the file like this
int c;
FILE myfile;
myfile= fopen("values.txt", "r");
if ( myfile == NULL ) {
printf("Cannot open TEXT file\n");
return 1;
}
double aa,bb;
while ( (c = getc(myfile) ) != EOF ) {
// HERE SHOULD I DO THE OUTPUT BUT HOW?
}
Any help is really appreciated ..
Language = C
The following code does what you expect. myfile should be declared as FILE*. fopen returns a pointer to FILE structure. If the file is very large, I would recommend reading in buffers of big size (eg: 65535 etc) and parse it char by char and convert it to float values. It reduces system call overhead which takes more time than processing text to float values.
#include <stdio.h>
#include <string.h>
main(int argc, char *argv[])
{
FILE* myfile;
myfile = fopen("values.txt", "r");
if ( myfile == NULL ) {
printf("Cannot open TEXT file\n");
return 1;
}
double aa,bb;
while (2 == fscanf(myfile, "%lf %lf", &aa, &bb)) {
printf("%lf\n", aa+bb);
}
return 0;
}
For this simple task, use double a, b;
if (fscanf(myfile, "%lf %lf", &a, &b) == 2)
printf("%f + %f = %f\n", a, b, a+b);.
looks like a homework problem but fscanf can read the string into a variable like:
int n;
fscanf (myfile,"%d",&n);
You haven't shown what you need as output for the single-value lines, but this looks like a case for fgets() and sscanf(), unless you really want the two lines with a single value to be processed as a unit.
char buffer[256];
int rownum = 0;
while (fgets(buffer, sizeof(buffer), myfile) != 0)
{
double aa, bb;
int n = sscanf(buffer, "%lf %lf", &aa, &bb);
if (n == 2)
printf("%d Pair:(%g, %g) = %g\n", ++rownum, aa, bb, aa+bb);
else if (n == 1)
printf("%d Solo:(%g) = %g\n", ++rownum, aa, aa);
else
{
printf("Failed to find any numbers in <<%s>>\n", buffer);
}
}
If you used fscanf(myfile, "%g %g", &aa, &bb), then it would read over newlines (they count as white space) looking for numbers, so it would read one number from one line, and the second from another line. This is not usually what people are after (but when it is what you need, it is extremely useful). Error recovery with fscanf() tends to be more fraught than with fgets() and sscanf().
its in c++ sorry :( i dont know c
this is a very simple logic code for simple minde :D im a begineer too, i havent tested this prog so sorry if something goes wrong but exactly
on a same principle was working my parser and it worked fine. so this is a true method. not very efficent but...
do not use this program straight away, understand it's logic this will help you alot. copying that wont give you anything
...parser tutors are so rare....
int x=0;
char ch = 'r'; //i'v used this equasion to avoid error on first ckeck of ch.
it must be filled by something when program starts.
char bigch[10];
int checknumber = 0;
float firstnumber = 0;
float secondnumber = 0;
float result=0;
void clearar(char frombigar[10], int xar) //this function gets bigch as a reference which means that eny
changes made here, will directly affect bigch itself.
ths function gets the actual length of array and puts spaces
in bigch's every element to zero out numbers. we need to clear
bigch of any previous numbers. down below you'l see why i needed this.
'xar' is the x from main function. its here to tell our cleaner the
true length of filled bigar elements.
{
for (int i=0; i
}
}
int main()
{
<------------------- //here you add file opening and reading commands
while(!myfile.eof()) //while end of txt file have not been reached
{
ch=myfile.get(); //gets each letter into ch, and make cursor one step
forward in txt file for further reading.
get() does cursor forwarding automatically
if (ch!= " ") //i used space as an indicator where one number ends
//so while space havent been reahced, read letters.
{ bigch[x] = ch; //get read letter into bigch array.
x++; //icrement bigch array step
}
else
if(ch == " ") //if space is reached that means one number has ended and
{ im trying to set a flag at that moment. it will be used further.
checknumber++; the flag is simple number. first space will set checknumber to 1
second space will set it to 2. thats all.
}
if (checknumber == 1) //if our checknumber is 1, wich means that reading
of first number is done, lets make one whole float
from that bigch array.
{ firstnumber = atof(bigch); //here we get bigch, atof (array to float) command converts
bigch array into one whole float number.
clearar(bigch,x); //here we send bigch and its element step into function where
bigch gets cleaned because we dont want some ghost numbers in it.
abviously clearar function cleans bigch int main function aswell,
not only in it's teritory. its a global cleaning :)
}
else if (checknumber ==2) //here we do the same but if flag is 2 this means that two spaces
had been passed and its time to convert bigch into secondnumber.
{ secondnumber = atof(bigch); //same method of converting array into float (it hates other
not number letters, i mean if its a number its fine. if in your text
was 'a' or 's' in that case atof will panic hehe.. )
clearar(bigch,x); //same thing, we send bigch to cleaner function to kill any numbers
it, we get one space letter ( " " ) into each element of bigch.
}
checknumber = 0; if both two numbers had been read out and converted. we need to reset
space flagger. and start counting form 0; for next pair numbers.
result = firstnumber+secondnumber; well here everything is clear.
}
}