So, I have a file like this:
12345 name1 18 500.000000
12345 name2 18 500.000000
And I wanted to read the file and each column go to a different variable. So I coded this:
void updateStruct() {
char c;
int lines, i;
accounts account[accMAX];
FILE *acc = fopen("acc.dat", "r+");
if (acc == NULL)
return;
for (c = getc(acc); c != EOF; c = getc(acc))
if (c == '\n')
lines += 1;
fscanf(acc, "%d %s %d %f", &account[0].number, account[0].name,
&account[0].age, &account[0].balance);
}
Somehow, the fscanf() doesn't attribute any value to the variables. What am I doing wrong?
The for loop leaves the file pointer at the end of the file. Call rewind to position the file pointer back at the start of the file before calling fscanf.
The for loop to compute the number of lines reads the whole file. fscanf() fails to convert anything and returns EOF.
You must rewind the position to the beginning of file with rewind(acc) or fseek(acc, 0L, SEEK_SET).
Note also that variable c must have type int for the EOF test to function correctly. Furthermore you should also count the last line that may or may not have a newline.
Here is a modified version:
accounts *updateStruct(int *countp) {
int c, last, lines, i;
FILE *acc = fopen("acc.dat", "r");
if (acc == NULL)
return NULL;
last = EOF;
while ((c = getc(acc)) != EOF) {
if (c == '\n')
lines += 1;
last = c;
}
if (last != '\n') { // last line did not have a newline
lines += 1;
}
rewind(acc);
accounts *account = calloc(lines, sizeof(account));
if (account == NULL) {
fclose(acc);
return NULL;
}
for (i = 0; i < count;) {
if (fscanf(acc, "%d %s %d %f", &account[i].number, account[i].name,
&account[i].age, &account[i].balance) != 4) {
// invalid line: skip to the newline
while ((c = getc(acc)) != EOF && c != '\n')
continue;
if (c == EOF)
break;
} else {
i++;
}
}
fclose(acc);
*countp = i;
return account;
}
Related
I'm trying to write a program that will read a file, and will output the lines of file. It will start with the last line, then will print the second to last line then the last line, second to last line then third to last line and so on and so forth. I almost have it figured out, but
It's the condition of the loop,
change while((c = fgetc(myFile) != EOF)) to while((c = fgetc(myFile)) != EOF)
around the code (c = fgetc....) is off.
Can someone help me fix this?
Thanks.
void tail(FILE* myFile, int num) //Tail function that prints the lines
according to the user specified number of lines
{
int start, line = 0, counter = 0;
char c, array[100];
while((c = fgetc(myFile) != EOF))
{
if(c=='\n')
line++;
}
start = line - num; //Start location
fseek(myFile, 0, SEEK_SET); //Goes to the start of the file
while(fgets(array, 100, myFile) != NULL)
{
if(counter >start)
{
printf("%s",array); //Prints the string
}
counter++;
}
fclose(myFile); //Closes the file
}
The first issue I see is this idiom:
while((c = fgetc(myFile) != EOF))
has the parens wrong, it should be:
while ((c = fgetc(myFile)) != EOF)
Also, this count:
start = line - num; //Start location
has an off-by-one error:
int start = line - num - 1; // Start location
Beyond that, your array seems too small for general text line processing:
char c, array[100];
Putting it all together with a few style tweaks, we get:
// Tail function that prints the lines
// according to the user specified number of lines
void tail(FILE *myFile, int num)
{
int line = 0;
char c;
while ((c = fgetc(myFile)) != EOF)
{
if (c == '\n')
{
line++;
}
}
int start = line - num - 1; // Start location
(void) fseek(myFile, 0, SEEK_SET); // Go to the start of the file
int counter = 0;
char array[1024];
while (fgets(array, sizeof(array), myFile) != NULL)
{
if (counter > start)
{
fputs(array, stdout); // Print the string
}
counter++;
}
fclose(myFile); // Close the file
}
it's about reading from a text file.
I have 3 command line arguments:
name of text file
delay time
how many line(s) want to read.
I want to read that text file by user specified line numbers till text file ends.
For example, the first time I read 5 lines and then the program asks how many line(s) do you want to read?. I would enter 7 it reads lines 5 to 12.
This would repeat until the end of the file.
#include <stdlib.h>
#include <stdio.h>
#include<time.h>
#include <string.h>
void delay(unsigned int mseconds)
{
clock_t goal = mseconds + clock();
while (goal > clock());
}
int countlines(const char *filename) {
FILE *fp = fopen(filename, "r");
int ch, last = '\n';
int lines = 0;
if (fp != NULL) {
while ((ch = fgetc(fp)) != EOF) {
if (ch == '\n')
lines++;
last = ch;
}
fclose(fp);
if (last != '\n')
lines++;
}
return lines;
}
int main(int argc, char *arg[])
{
FILE *ptDosya;
char ch;
ch = arg[1][0];
int s2;
int satir = 0;
int spaceCounter=0;
int lineCount, x = 0;
lineCount = atoi(arg[3]);
s2 = atoi(arg[2]);
printf("dosya %d satir icerir.\n", countlines(arg[1]));
ptDosya = fopen(arg[1], "r");
if (ptDosya != NULL)
{
while (ch != EOF&& x < lineCount)
{
ch = getc(ptDosya);
printf("%c", ch);
if (ch == '\n')
{
delay(s2);
x++;
}
}
while (x < countlines(arg[1]))
{
printf("satir sayisi giriniz:");
scanf("%d", &lineCount);
// i don't know what should i do in this loop..
x=x+lineCount;
}
}
else {
printf("dosya bulunamadi");
}
printf("\n\nend of file!\n");
fclose(ptDosya);
return 0;
system("PAUSE");
}
Your delay function uses a busy loop. This is unnecessarily expensive in terms of computing power. It would be very unwelcome to do this on a battery operated device. Furthermore, clock() does not necessarily return a number of milliseconds. The unit used by the clock() function can be determined using the CLOCKS_PER_SEC macro. Unfortunately, there is no portable way to specify a delay expressed in milliseconds, POSIX conformant systems have usleep() and nanosleep().
Your line counting function is incorrect: you count 1 line too many, unless the file ends without a trailing linefeed.
Here is an improved version:
int countlines(const char *filename) {
FILE *fp = fopen(filename, "r");
int ch, last = '\n';
int lines = 0;
if (fp != NULL) {
while ((ch = fgetc(fp)) != EOF) {
if (ch == '\n')
lines++;
last = ch;
}
fclose(fp);
if (last != '\n')
lines++;
}
return lines;
}
There are issues in the main() function too:
You so not verify that enough arguments are passed on the command line.
You do not check for EOF in the main reading loop.
You do not repeat the process in a loop until end of file, nor do you even ask the question how many line(s) do you want to read? after reading the specified number of lines...
First, if the file cannot be found, the countlines method returns zero. You should use that value to write the error message, and skip the rest of the code.
Second, in the next loop, you use
if (ch != '\n') {
printf("%c", ch);
} else {
printf("\n");
delay(s2);
x++;
}
Why the two printf statements? They will print the same thing.
Perhaps something like this:
ch = getc(ptDosya);
/* exit the loop here if you hit EOF */
printf("%c", ch); /* Why not putc() or putchar() ? */
if (ch == '\n') {
x++;
if ( x == lineCount ) {
x = 0;
lineCount = requestNumberOfLinesToRead();
} else {
sleep(s2); /* instead of delay(). Remember to #include unistd.h */
}
}
My program requires to get input from a textfile and output it on a single line.
However if the amount of characters on a singular line exceed 60, there should be a new line.
The code I have so far:
int main(int argc, char *argv[]){
FILE *pFile;
char x[10];
char *token;
pFile = fopen("test5.txt","r");
int wordLength;
int totalCharLength;
char newline[10] = "newline";
if(pFile != NULL){
while (fgets(x, sizeof(x), pFile) != NULL) {
token = strtok(x,"\r\n");
if(token != NULL){
printf("%s",x);
}
else{
printf("%s",x);
}
//counter++;
wordLength = strlen(x);
totalCharLength += wordLength;
printf("%d",totalCharLength);
if(totalCharLength == 60){
printf("%s",newline);
}
}
fclose(pFile);
}
}
Textfile:
a dog chased
a cat up the
tree. The cat
looked at the dog from
the top of the tree.
There are 5 separate lines. Which displays this. This is not all on one line.
Output:
a dog chased a cat up the tree. The cat looked at the dog from the top of the tree.
Now the program needs to be able to get input text in that format and print out in a single line.
So the above Output there should be a new line at the 60th char which is before second word "dog".
However I want to add a feature so that there is a counter for character and it prints a new line when character count = 60.
Now with some more debugging I added the code
printf("%d",totalCharLength);
just before the if(totalCharLength==60) line and I realize that the characters get counted in random increments instead of one by one. Output:
a dog cha9sed 13a cat up 22the 26tree. The35 cat 40looked at49 the dog 58 from 63 the top o72f the tre81e. 85
So this shows that it does not count character by character. However when I change charx[10] to a lower value it does not print everything on one line. It will leave gaps.
Example: Changing charx[10] to charx[2]
This correctly gets character by character however the output is not in on one line.
The only time there should be a new line is when characters exceed 60 in a line. Not 14 (First line).
a2 3d4o5g6 7c8h9a10s11e12d13 14
30a17 18c19a20t21 22u23p24 25t26h27e28 29
46t32r33e34e35.36 37T38h39e40 41c42a43t44 45
71l48o49o50k51e52d53 54a55t56 57t58h59e60newline 61d62o63g64 65f66r67o68m69 70
72t73h74e75 76t77o78p79 80o81f82 83t84h85e86 87t88r89e90e91.92 93 94
I think you are best just printing each char on his own, and check for a space before adding the newline.
Something like:
((charCount > 60) && (currentChar == ' ')) {
// print newline and reset counter
printf("\n");
charCount = 0;
}
Edit:
before anything check if the current char is a newline already and skip it.
Check the carriage return \r as well since in windows newlines are \r\n.
#include <stdio.h>
int main(void) {
FILE *f = fopen("test.txt", "r");
if(!f) {
printf("File not found.\n");
return 1;
}
char c;
int cCount = 0;
while((c = fgetc(f)) != EOF) {
if(c == '\r') continue;
if(c == '\n') c = ' ';
printf("%c", c);
if((cCount++ > 60) && (c == ' ')) {
printf("\n");
cCount = 0;
}
}
fclose(f);
return 0;
}
There you go
int main() {
FILE *pFile = fopen("test.txt","r");
int c, counter = 0;
if (pFile != NULL) {
while ((c = getc(pFile)) != EOF) {
counter++;
if (c != '\n') { putchar(c); }
if (counter == 60) {
counter = 0;
printf("\n");
}
}
}
fclose(pFile);
}
if(token != NULL){
printf("%s",x);
strcat(newArray, x);
}
After printing out the token, have a separate array that you concatenate the token too. This will give you the entire file on one line. It will be much easier from here to parse out the 60 characters then print lines as you go.
It goes like this,
#include<stdio.h>
//#pragma warning(disable : 4996)
int main()
{
FILE *pfile;
char data;
int count = 1;
pfile = fopen("test.txt", "r");
printf("Opening file...\n");
if (pfile == NULL)
{
printf("Error!\n");
}
while ((data = fgetc(pfile)) != EOF)
{
if (count != 60)
{
if (data != '\n')
{
printf("%c", data);
count++;
}
}
else
{
printf("\n");
count = 1;
}
}
fclose(pfile);
return 0;
}
In the first case, when you had char x[10], fgets will read up to 9 characters, or until a newline is found. So the output is
a dog cha9sed 13a cat up 22the 26
because the first call to fgets reads 9 characters (and then prints 9), the second call reads up to the newline (prints 13), the third call reads nine characters (prints 22), and the fourth call reads up to the newline (prints 26).
When you change to char x[2], fgets will only read one character at a time. And this causes strtok to work differently than you expect. When a string contains only delimiter characters, strtok will return NULL and the string is unmodified. So if the string contains only a newline character, strtok won't remove the newline, like you expect.
To fix the code, use fgetc to read characters and don't use strtok at all.
int main( void )
{
FILE *pFile;
if ( (pFile = fopen("test5.txt","r")) == NULL )
exit( 1 );
int c, count;
count = 0;
while ( (c = fgetc(pFile)) != EOF ) {
if ( c == '\n' )
putchar( ' ' );
else
putchar( c );
count++;
if ( count == 60 ) {
putchar( '\n' );
count = 0;
}
}
putchar( '\n' );
fclose(pFile);
}
Here's the file that I tested with
a dog chased
a cat up the
tree. The cat
looked at the dog from
the top of the tree.
#include <stdio.h>
#include <ctype.h>
int main(void){//unused argv
FILE *pFile;
int ch, prev = 0;
int totalCharLength = 0;
int wrap_size = 60;
//char newline[] = "newline";
pFile = fopen("test5.txt","r");
if(pFile != NULL){
while((ch = fgetc(pFile)) != EOF){
if(isspace(ch))
ch = ' ';
if(prev == ' ' && ch == ' ')
continue;//unified
prev = ch;
putchar(ch);
if(++totalCharLength == wrap_size -1){//-1 : include newline
putchar('\n');//printf("%s", newline);
totalCharLength = 0;
}
}
fclose(pFile);//put inside if-block
}
return 0;
}
I'm writing a function that reads the number of lines in the given line. Some text files may not end with a newline character.
int line_count(const char *filename)
{
int ch = 0;
int count = 0;
FILE *fileHandle;
if ((fileHandle = fopen(filename, "r")) == NULL) {
return -1;
}
do {
ch = fgetc(fileHandle);
if ( ch == '\n')
count++;
} while (ch != EOF);
fclose(fileHandle);
return count;
}
Now the function doesn't count the number of lines correctly, but I can't figure out where the problem is. I would be really grateful for your help.
Here is another option (other than keeping track of last character before EOF).
int ch;
int charsOnCurrentLine = 0;
while ((ch = fgetc(fileHandle)) != EOF) {
if (ch == '\n') {
count++;
charsOnCurrentLine = 0;
} else {
charsOnCurrentLine++;
}
}
if (charsOnCurrentLine > 0) {
count++;
}
fgets() reads till newline character or till the buffer is full
char buf[200];
while(fgets(buf,sizeof(buf),fileHandle) != NULL)
{
count++;
}
fgetc() is an issue here because you encounter EOF first and exit your do while loop and never encounter a \n character so count remains untouched for the last line in your file.If it happens to be there is a single line in your file that the count will be 0
int periodCount(const char *filename) {
FILE * fp;
int n = 0;
if( (fp=fopen(filename,"r")) != NULL) {
while(fgetc(fp)!= EOF) {
if(fgetc(fp)=='.') n++;
fclose(fp);
}
}
return n;
}
Here is my code, it simply should count the number of periods in the file named filename, which contains 15 periods, yet when I try to print 'n' at the end of the program, it seems to only be reading 1 of the periods. I know that the problem is probably within the while loop, but I'm not sure why it's doing it.
You're closing the file after the first character. Also you're skipping every other character as a result of not storing the return from fgetc(). Change to:
int periodCount(const char *filename) {
FILE * fp;
int n = 0, c = 0;
if( (fp=fopen(filename,"r")) != NULL) {
while( (c = fgetc(fp)) != EOF) {
if( c == '.' )
n++;
}
fclose(fp); /* <---- move this line here */
}
return n;
}
Your fclose(fp) should be outside the while loop.
As it is, the code is reading (& discarding) the first character; reading the 2nd character & comparing it to '.'; and closing the file.
There are two problems:
You have two calls to fgetc() but you only test whether one of them returned a dot.
You close the file stream in the body of the loop.
You need something more like:
if ((fp = fopen(filename,"r")) != NULL)
{
int c;
while ((c = fgetc(fp)) != EOF)
{
if (c == '.')
n++;
}
fclose(fp);
}