I'm trying to read the number of a txt file like this:
input=20
output=10
hidden=5
....
I tried with this code:
char line[30];
char values[100][20];
int i = 0;
FILE *fp;
fp = fopen("myFile.txt", "r");
if(fp == NULL)
{
printf("cannot open file\n");
return 0;
}
while(fgets(line, sizeof(line), fp) != NULL)
{
sscanf(line, "%[^=]", values[i])
printf("%s\n", values[i]);
i++;
}
fclose(fp);
But I obtain only the first word and never the number after the =.
I get
input
output
etc
instead of
20
10
5
etc
How can I get the number??
This line
sscanf(line, "%[^=]", values[i]);
means "read everything up to, but not including, the = sign into values[i]".
If you are interested in the numeric part after the equal sign, change the call as follows:
sscanf(line, "%*[^=]=%19s", values[i]);
This format line means "read and ignore (because of the asterisk) everything up to, and including, the equal sign. Then read a string of length of up to 19 characters into values[i]".
Demo.
Don't use sscanf() for that, redeclare values to store the integers like
int values[LARGE_CONSTANT_NUMBER];
and after fgets() just use strchr
char *number;
number = strchr(line, '=');
if (number == NULL)
continue;
number += 1;
values[i] = strtol(number, NULL, 10);
you could also use malloc() and realloc() if you wish, to make the values array dynamic.
Try it if you like
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
char line[100];
int values[100];
int i;
FILE *fp;
size_t maxIntegers;
fp = fopen("myFile.txt", "r");
if (fp == NULL)
{
perror("cannot open file\n");
return 0;
}
i = 0;
maxIntegers = sizeof(values) / sizeof(values[0]);
while ((fgets(line, sizeof(line), fp) != NULL) && (i < maxIntegers))
{
char *number;
number = strchr(line, '=');
if (number == NULL) /* this line does not contain a `=' */
continue;
values[i++] = strtol(number + 1, NULL, 10);
printf("%d\n", values[i - 1]);
}
fclose(fp);
return 0;
}
with this technique you avoid unecessarily storing the number as a string.
Related
I need help to read the numbers of a .txt file and put them in an array. But only from the second line onwards. I'm stuck and don't know where to go from the code that i built.
Example of the .txt file:
10 20
45000000
48000000
56000000
#define MAX 50
int main (void){
FILE *file;
int primNum;
int secNum;
int listOfNumers[50];
int numberOfLines = MAX;
int i = 0;
file = fopen("file.txt", "rt");
if (file == NULL)
{
printf("Error\n");
return 1;
}
fscanf(file, "%d %d\n", &primNum, &secNum);
printf("\n1st Number: %d",primNum);
printf("\n2nd Number: %d",secNum);
printf("List of Numbers");
for(i=0;i<numberOfLines;i++){
//Count the number from the second line onwards
}
fclose(file);
return 0;
}
You just need a loop to keep reading ints from file and populate the listOfNumers array until reading an int fails.
Since you don't know how many ints there are in the file, you could also allocate the memory dynamically. Example:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE* file = fopen("file.txt", "rt");
if(file == NULL) {
perror("file.txt");
return 1;
}
int primNum;
int secNum;
if(fscanf(file, "%d %d", &primNum, &secNum) != 2) {
fprintf(stderr, "failed reading primNum and secNum\n");
return 1;
}
unsigned numberOfLines = 0;
// allocate space for one `int`
int* listOfNumers = malloc((numberOfLines + 1) * sizeof *listOfNumers);
// the above could just be:
// int* listOfNumers = malloc(sizeof *listOfNumers);
while(fscanf(file, "%d", listOfNumers + numberOfLines) == 1) {
++numberOfLines;
// increase the allocated space by the sizeof 1 int
int* np = realloc(listOfNumers, (numberOfLines + 1) * sizeof *np);
if(np == NULL) break; // if allocating more space failed, break out
listOfNumers = np; // save the new pointer
}
fclose(file);
puts("List of Numbers:");
for(unsigned i = 0; i < numberOfLines; ++i) {
printf("%d\n", listOfNumers[i]);
}
free(listOfNumers); // free the dynamically allocated space
}
There are a few ways to approach this; if you know the size of the first line, you should be able to use fseek to move the position of the file than use getline to get each line of the file:
int fseek(FILE *stream, long offset, int whence);
The whence parameter can be:
SEEK_SET : the Beginning
SEEK_CUR : the current position
SEEK_END : the End
The other option would to encapsulate the entire file read in a while loop:
char *line = NULL;
size_t linecap = 0;
ssize_t linelen;
int counter = 0;
while((linelen = getline(&line, &linecap, file)) != -1){
if counter == 0{
sscanf(line, "%d %d\n", &primNum, &secNum);
}else{
//Process your line
}
counter++; //This would give you your total line length
}
I'm trying to read a file that contains 10 numbers then adding them to an array so I can sort them later on but I'm having trouble reading them in. Not sure why this isn't working for me, can someone explain what is wrong? There's only a number on each lines.
10.05
11.01
9.03
double nums[10] = {0};
int count;
if ((fptr = fopen("filename", "r")) == NULL){
printf("Error opening file.\n");
}
while ((c = getc(fptr)) != EOF){
if (c != '\n'){
nums[count] = (double)c;
count = count + 1;
}
}
fclose(fptr);
What is wrong:
You are storing only one character.
You are updating count each times on non-newline characters while updating should be on newline characters.
count is used without being initialized.
Casting to double is not for this usage.
Possible fix:
int c;
FILE* fptr;
char line[1024]; // add line buffer and size tracking
int lineCount = 0;
double nums[10] = {0};
int count = 0; // initialize count
if ((fptr = fopen("filename", "r")) == NULL){
printf("Error opening file.\n");
} else { // avoid using NULL to read file
while ((c = getc(fptr)) != EOF){
if (c == '\n'){ // update nums on newline character
line[lineCount] = '\0'; // don't forget to terminate the string
nums[count] = atof(line); // atof() from stdlib.h is useful to convert string to number
count = count + 1;
lineCount = 0; // start to read next line
} else { // read line contents
line[lineCount] = (char)c;
lineCount = lineCount + 1;
}
}
fclose(fptr);
}
Here I go
#include <stdio.h>
#include <stdlib.h>
int main()
{
double values[10];
int count;
FILE *f = fopen("filename", "r");
if (f == NULL)| {
fprintf(stderr, "Some error message");
return EXIT_FAILURE; // We cannot go any further - file is dead
}
// This is basic - you could overcome error problems
// When able to read (including white space) we carry on until the array is full
// This is an area for improvement - error checking etc.
for (count = 0; count < 10 && fscanf(f, " %lf", &values[count]) != 1; count ++);
fclose(f);
return EXIT_SUCCESS;
}
My goal is to create two variables in C from the text file that can be used later in the code. My first variable will be the data from lines 1, 3, 5, 7 and so on. The second variable will be the data from lines 2, 4, 6, and so on.
Main function:
#include <stdio.h>
int main() {
FILE *file;
char buf[500];
file = fopen("ANTdata.txt", "r");
if (!file) {
return 1;
}
while (fgets(buf, 500, file) != NULL) {
printf("%s", buf);
}
fclose(file);
return 0;
}
Example of text file:
0.0002746660
-0.0013733300
-0.0002136290
-0.0002746660
0.0021362900
-0.0006103680
0.0006103680
-0.0022583600
-0.0011291800
-0.0005798500
0.0000000000
-0.0001831100
0.0000915552
-0.0015259200
Your problem can be solved easily with fscanf():
#include <stdio.h>
int main() {
FILE *file;
double x1[1000], x2[1000];
int n;
file = fopen("ANTdata.txt", "r");
if (!file) {
return 1;
}
for (n = 0; n < 1000 && fscanf(file, "%lf%lf", &x1[n], &x2[n]) == 2; n++)
continue;
fclose(file);
/* arrays x1 and x2 have `n` elements, perform your computations */
...
return 0;
}
If you just want to handle 2 lines at a time with a different function, here is a simple solution:
#include <stdio.h>
#include <string.h>
void my_function(const char *line1, const char *line2) {
printf("x: %s, y: %s\n", line1, line2);
}
int main() {
FILE *file;
char line1[250], line2[250];
file = fopen("ANTdata.txt", "r");
if (!file) {
return 1;
}
while (fgets(line1, sizeof line1, file) && fgets(line2, sizeof line2, file)) {
/* strip the trailing newlines if any */
line1[strcspn(line1, "\n")] = '\0';
line2[strcspn(line2, "\n")] = '\0';
my_function(line1, line2);
}
fclose(file);
return 0;
}
Here is a simple anwser (can be improved) :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
FILE * fp;
fp = fopen("ANTdata.txt", "r");
char * line;
char oddLine[100];
char evenLine[100];
if (fp == NULL)
exit(EXIT_FAILURE);
int i = 0;
int endOfFile = 1;
int res = 0;
size_t len = 0;
while(endOfFile)
{
if(i % 2 == 0){
res = getline(&line, &len, fp);
strcpy(evenLine, line);
printf("even : %s", evenLine);
}else{
res = getline(&line, &len, fp);
strcpy(oddLine, line);
printf("odd : %s", oddLine);
}
if(res == -1)
endOfFile = 0;
i++;
}
fclose(fp);
return 0;
}
The output is :
even : 0.0002746660
odd : -0.0013733300
even : -0.0002136290
odd : -0.0002746660
even : 0.0021362900
odd : -0.0006103680
even : 0.0006103680
odd : -0.0022583600
even : -0.0011291800
odd : -0.0005798500
even : 0.0000000000
odd : -0.0001831100
even : 0.0000915552
odd : -0.0015259200
even : -0.0015259200
You can use strtod to convert a text representation of a floating point value to floating point:
#include <stdlib.h>
...
char *chk;
double x = strtod( buf, &chk );
chk will point to the first character not converted - if that character is not whitespace or a string terminator, then your input was not a valid float constant:
if ( !isspace( *chk ) && *chk != 0 )
{
// bad input, handle as appropriate
}
If you don't want to bother with error checking (you know your input file is good), you can pass NULL as the second argument.
How you handle assigning which input to which variable is up to you. If you want to keep your current loop structure (loop while valid input is read), you'll need a way to keep track of which row you're on, and then decide based on that. Here's one (somewhat fragile) approach:
int xvals[N], yvals[N];
int row = 0, i = 0;
while ( fgets ( buf, sizeof buf, file ) )
{
if ( ++row % 2 ) // row is odd
xvals[i] = strtod( buf, NULL ); // error checking omitted for brevity
else
yvals[i++] = strtod( buf, NULL ); // advance i after both x and y are read
...
}
Supposing that I have two files like this:
file1.txt
john
is
the new
guy
file2.txt
man
the old
is
rick
cat
dog
I'd like to compare first line from file1 with all the lines from file2 and verify if it exist. If not, go two the second line from file1 and compare it with all the lines from file2.. and so on until eof is reached by file1.
The output that I expect is:
john
the new
guy
How I thought this should be done:
read file1 and file2
create a function which returns the line number of each of them
take the first line from file1 and compare it to all the lines from file2
do this until all the lines from file1 are wasted
Now, I don't know what I'm doing wrong, but I don't get the result that I expect:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int countlines(char *filename)
{
int ch = 0, lines = 0;
FILE *fp = fopen(filename, "r");
if (fp == NULL)
return 0;
do {
ch = fgetc(fp);
if (ch == '\n')
lines++;
} while (ch != EOF);
if (ch != '\n' && lines != 0)
lines++;
fclose(fp);
return lines;
}
int main(int argc, char *argv[])
{
FILE *template_file = fopen(argv[1], "r");
FILE *data_file = fopen(argv[2], "r");
char buffer_line_template_file[100];
char buffer_line_data_file[100];
if (argc != 3)
{
perror("You didn't insert all the arguments!\n\n");
exit(EXIT_FAILURE);
}
if (template_file == NULL || data_file == NULL)
{
perror("Error while opening the file!\n\n");
exit(EXIT_FAILURE);
}
int counter = 0;
for (int i = 0; i < countlines(argv[1]); i++)
{
fgets(buffer_line_template_file, 100, template_file);
for (int j = 0; j < countlines(argv[2]); j++)
{
fgets(buffer_line_data_file, 100, data_file);
if (strcmp(buffer_line_template_file, buffer_line_data_file) != 0)
{
counter++;
printf("%d", counter);
}
}
}
printf("\n\n");
return 0;
}
Could someone please point me into the right direction ? For testing purposes I created a counter at the end which was a part of a small debug. There should be the print() function
As per #chux answer I got the following simplified code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *template_file = fopen(argv[1], "r");
FILE *data_file = fopen(argv[2], "r");
char buffer_line_template_file[100];
char buffer_line_data_file[100];
if (argc != 3)
{
perror("You didn't insert all the arguments!\n\n");
exit(EXIT_FAILURE);
}
if (template_file == NULL || data_file == NULL)
{
perror("Error while opening the file!\n\n");
exit(EXIT_FAILURE);
}
while(fgets(buffer_line_template_file, 100, template_file))
{
buffer_line_template_file[strcspn(buffer_line_template_file, "\n")] = '\0';
rewind(data_file);
while (fgets(buffer_line_data_file, 100, data_file))
{
buffer_line_data_file[strcspn(buffer_line_data_file, "\n")] = '\0';
if (strcmp(buffer_line_template_file, buffer_line_data_file) != 0)
{
printf("%s\n", buffer_line_template_file);
}
}
}
printf("\n\n");
return 0;
}
The above code is giving me the following output, which is not what is expected:
john
john
john
john
john
john
is
is
is
is
is
the new
the new
the new
the new
the new
the new
guy
guy
guy
guy
guy
guy
Problems with OP's code
Imprecise definition of line.
Excessive recalculation
Fuzzy determination of the number of lines in a file.
Unlike string, which has a precise definition in C, reading a line is not so well defined. The primary specificity issue: does a line contain the trailing '\n'. If the first answer is Yes, then does the last text in a file after a '\n' constitute a line? (Excessively long lines are another issue, but let us not deal with that today.)
Thus possibly some lines end with '\n' and others do not, fooling strcmp("dog", "dog\n").
The easiest solution is to read a line until either 1) a '\n' is encountered, 2) EOF occurs or 3) line buffer is full. Then after getting a line, lop off the potential trailing '\n'.
Now all lines code subsequently works with have no '\n'.
fgets(buffer_line_template_file, 100, template_file);
buffer_line_template_file[strcspn(buffer_line_template_file, "\n")] = '\0';
OP's loop is incredible wasteful. Consider a file with 1000 lines. Code will loop, calling 1000 times countlines() (each countlines() call reads 1000 lines) times when one countlines() call would suffice.
// for (int j = 0; j < countlines(argv[2]); j++)
int j_limit = countlines(argv[2]);
for (int j = 0; j < j_limit; j++)
There really is no need to count the line anyways, just continue until EOF (fgets() returns NULL). So no need to fix its fuzzy definition. (fuzzy-ness concerns same issues as #1)
int counter = 0;
for (fgets(buffer_line_template_file, 100, template_file)) {
buffer_line_template_file[strcspn(buffer_line_template_file, "\n")] = '\0';
rewind(data_file);
while ((fgets(buffer_line_data_file, 100, data_file)) {
buffer_line_data_file[strcspn(buffer_line_data_file, "\n")] = '\0';
if (strcmp(buffer_line_template_file, buffer_line_data_file) != 0) {
counter++;
printf("%d", counter);
}
}
}
Other simplifications possible - for another day.
FWIW, following counts lines of text allowing the last line in the file to optionally end with a '\n'.
unsigned long long FileLineCount(FILE *istream) {
unsigned long long LineCount = 0;
rewind(istream);
int previous = '\n';
int ch;
while ((ch = fgetc(inf)) != EOF) {
if (previous == '\n') LineCount++;
previous = ch;
}
return LineCount;
}
Note that this function may get a different result that fgets() calls. Consider a file of one line of 150 characters. fgets(..., 100,...) will report 2 lines. FileLineCount() reports 1.
[Edit] Updated code to conform to OP functionality.
int found = 0;
while (fgets(buffer_line_data_file, 100, data_file))
{
buffer_line_data_file[strcspn(buffer_line_data_file, "\n")] = '\0';
if (strcmp(buffer_line_template_file, buffer_line_data_file) == 0)
{
found = 1;
break;
}
}
if (!found) printf("%s\n", buffer_line_template_file);
This program prints the diff of two files file1.txt and file2.txt.
#include<stdio.h>
#include <stdlib.h>
#include <memory.h>
int main() {
FILE *fp1, *fp2;
int ch1, ch2;
char fname1[40], fname2[40];
char *line = NULL;
size_t len = 0;
ssize_t read;
char *line2 = NULL;
size_t len2 = 0;
ssize_t read2;
fp1 = fopen("file1.txt", "r");
fp2 = fopen("file2.txt", "r");
if (fp1 == NULL) {
printf("Cannot open %s for reading ", fname1);
exit(1);
} else if (fp2 == NULL) {
printf("Cannot open %s for reading ", fname2);
exit(1);
} else {
while ((read = getline(&line, &len, fp1)) != -1 && (read2 = getline(&line2, &len2, fp2)) != -1) {
if (!strcmp(line, line2)) {
printf("Retrieved diff on line %zu :\n", read);
printf("%s", line);
}
}
if (ch1 == ch2)
printf("Files are identical \n");
else if (ch1 != ch2)
printf("Files are Not identical \n");
fclose(fp1);
fclose(fp2);
}
return (0);
}
You already have a very good answer (and always will from chux), but here is a slightly different approach to the problem. It uses automatic storage to reading file2 into an array of strings and then compares each line in file1 against every line in file2 to determine whether it is unique. You can easily convert the code to dynamically allocate memory, but for sake of complexity that was omitted:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXC = 256, MAXL = 512 };
void file1infile2 (FILE *fp2, FILE *fp1, size_t *n2, size_t *n1);
int main (int argc, char **argv) {
FILE *fp1 = fopen (argc > 1 ? argv[1] : "file1.txt", "r");
FILE *fp2 = fopen (argc > 2 ? argv[2] : "file2.txt", "r");
size_t n1 = 0, n2 = 0;
if (!fp1 || !fp2) {
fprintf (stderr, "error: file open failed.\n");
return 1;
}
printf ("\nunique words in file1, not in file 2.\n\n");
file1infile2 (fp2, fp1, &n2, &n1);
printf ("\nanalyzed %zu lines in file1 against %zu lines in file2.\n\n",
n1, n2);
return 0;
}
void file1infile2 (FILE *fp2, FILE *fp1, size_t *n2, size_t *n1)
{
char buf[MAXC] = "";
char f2buf[MAXL][MAXC] = { "" };
size_t i;
*n1 = *n2 = 0;
while (*n2 < MAXL && fgets (buf, MAXC, fp2)) {
char *np = 0;
if (!(np = strchr (buf, '\n'))) {
fprintf (stderr, "error: line exceeds MAXC chars.\n");
exit (EXIT_FAILURE);
}
*np = 0;
strcpy (f2buf[(*n2)++], buf);
}
while (*n1 < MAXL && fgets (buf, MAXC, fp1)) {
char *np = 0;
if (!(np = strchr (buf, '\n'))) {
fprintf (stderr, "error: line exceeds MAXC chars.\n");
exit (EXIT_FAILURE);
}
*np = 0, (*n1)++;
for (i = 0; i < *n2; i++)
if (!(strcmp (f2buf[i], buf)))
goto matched;
printf (" %s\n", buf);
matched:;
}
}
Look over the code and let me know if you have any questions.
Example Use/Output
$ ./bin/f1inf2 dat/f1 dat/f2
unique words in file1, not in file 2.
john
the new
guy
analyzed 4 lines in file1 against 6 lines in file2.
I'm trying to read in a file with a couple hundred integers, some positive, some negative and store them in an array. They have to be read in as a string using strtok, though. I keep getting a segmentation fault and I'm not sure why. The count is to figure out how many total integers are in the file.
/*Input file looks like this:
718321747 -1828022042
-1665405912 -175307986
-53757018 -1551069786 525902369
-1945908378 853648883
*/
int main(int argc, char* argv[])
{
char buffer[50];
char* token;
int count = 0;
int num = 0;
int arr[MAX_SIZE];
if (argc != 2)
{
printf("Invalid number of arguments\n");
return 0;
}
FILE* fptr = fopen(argv[1], "r");
//open file
if (fptr == NULL)
{
printf("Unable to open file\n");
return 0;
}
while(fgets(buffer, 50, fptr))
//to get the file line by line
{
token = strtok(buffer, "\n\t ");
//find first token
num = atoi(token);
//convert it to an int
arr[count] = num;
//store in array
count++;
while(token != NULL)
//get rest of tokens and convert to int
{
token = strtok(buffer, "\n\t ");
num = atoi(token);
arr[count] = num;
count++;
}
}
return 0;
}
You never check if the token was found in the string, you must check that strtok() didn't return NULL before trying to call atoi().
Then you keep scanning the same string with strtok() passing the string in each iteration, that's also wrong, you should pass NULL after the first time.
I would also recommend to use strtol() instead of atoi() to check if the conversion was successful.
Check this code, i fixed it
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 1000 /* ? whatever value you think is good. */
int main(int argc, char* argv[])
{
char buffer[50];
int count = 0;
int arr[MAX_SIZE];
if (argc != 2)
{
printf("Invalid number of arguments\n");
return 0;
}
FILE* fptr = fopen(argv[1], "r");
//open file
if (fptr == NULL)
{
printf("Unable to open file\n");
return 0;
}
//to get the file line by line
while ((fgets(buffer, 50, fptr) != NULL) && (count < MAX_SIZE))
{
char *pointer;
char *token;
pointer = buffer;
while (((token = strtok(pointer, "\n\t ")) != NULL) && (count < MAX_SIZE))
{
char *endptr;
arr[count] = strtol(token, &endptr, 10);
printf("%d\n", arr[count]);
if (*endptr != '\0')
printf("error: could not convert %s to integer\n", token);
else
count++;
pointer = NULL;
}
}
return 0;
}
I am not sure it will work for you because I haven't seen the structure of your input data, but I am sure it will not cause a segmentation fault.