C - read TXT change from dup to fgets and sscanf - c

I read from txt pairs of numbers
How check it only 2 numbers in each line and not 3. I want show the line is the problem for example the pairs file:
3
25 35
14 42
30 60 70
Console: illegal input at line 4
I know That's not the correct way at all. Need use fgets to read and sscanf to parse.
I tried but the memory full garbage. How can I change it correctly?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i, c;
FILE *fp;
char str[100];
fp = fopen("./pairs.txt", "r");
if (dup2(fileno(fp), STDIN_FILENO < 0))
{
printf("Error opening file");
return -1;
}
if (feof(fp))
printf("Error reading file");
scanf("%d", &numOfPairs);
arrNum = (int *)malloc(sizeof(int) * numOfPairs * numbersInPair);
for (int i = 0; i < numOfPairs * numbersInPair; i += 2)
{
int num1, num2;
scanf("%d %d", &num1, &num2);
arrNum[i] = num1;
arrNum[i + 1] = num2;
}
}
Another try NOT working:
int main(int argc, char *argv[])
{
int index, i, numOfPairs;
int c;
FILE *file;
file = fopen("./pairs.txt", "r");
if ((c = getc(file)) == EOF)
{
perror("Error opening file"); //or return 1;
fclose(file);
}
while ((c = getc(file)) != EOF)
putchar(c);
{
fscanf(file, "%d", &numOfPairs);
allNumbers = (int *)malloc(sizeof(int) * numOfPairs * numbersInPair); //need multiply in 2 numbers for each pair
while (!feof(file) && numOfPairs > 0)
{
int x, y, arrIndex = 0;
numOfPairs--;
fscanf(file, "%d %d", &x, &y);
allNumbers[arrIndex] = x;
printf("The X : %d\n", x);
allNumbers[arrIndex + 1] = y;
printf("THE Y : %d\n", y);
arrIndex + 2;
}
fclose(file);
}

Related

fgetc() doesn't work properly in function

I am trying to read a text file, character by character, with fgetc() function but it does not show any output. It is a school project and it is still in very very simple way just to test the functionality of the program.
#include <stdio.h>
#include <stdlib.h>
void fn1(FILE *f);
void fn9(FILE *fp, char, char);
int main() {
FILE *fp = fopen("text.txt", "r");
if (fp == NULL) {
perror("Error: ");
exit(1);
}
fn1(fp);
fn9(fp, '0', '9');
fclose(fp);
return 0;
}
void fn1(FILE *f) {
int num, sum = 0, count = 0;
while (fscanf(f, "%d", &num) == 1) {
if (num > 0) {
sum += num;
count++;
}
}
printf("the avg of positive nums is %.2f", (float) sum / count);
}
void fn9(FILE *fp, char m, char n) {
int ch;
int count1 = 0, count2 = 0;
while ((ch = fgetc(fp)) != EOF) {
if (ch == m)
count1++;
if (ch == n)
count2++;
printf("%c", ch);
if (ferror(fp))
break;
}
printf("\n%c is seen %d times", m, count1);
printf("\n%c is seen %d times", n, count2);
fclose(fp);
}
The file's content that I test is:
90
16
-34
100
After fn(fp) return, fp will point to the last location in the file. It needs to be reset to the start of file before fn9 is called. Use fseek to point fp to the start of file and it should work :)

Storing numbers as (x, y) cordinates from a file at a specific point

I have an Instance File from which I need to store the NUM_PT and all the respective co-ordinates in the form of a 2D array system (personal choice so I can access them easily). I am able to retrieve the NUM_PT but I am stuck at reading the successive cordinates into my array.
HERE IS WHAT I HAVE DONE
/* Assignment 2 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#define MAXS 256
int main(int argc, char *argv[])
{
int num_pt;
int inputfile = 0, outputfile = 0, i;
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], "-i") == 0)
inputfile = i+1;
if (strcmp (argv[i], "-o") == 0)
outputfile = i+1;
}
if (inputfile == 0)
{
/* invalid command line options */
printf("\nIncorrect command-line...\n");
printf("> %s [-i inputfile [-o outputfile]]\n\n", argv[0]);
exit(0);
}
FILE *fp;
fp = fopen(argv[inputfile], "r");
int count = 0;
if (fp == 0)
{
printf("\nCould not find %s\n", argv[inputfile]);
exit(0);
}
char line[MAXS];
while (fgets(line, sizeof line, fp) != NULL)
{
if (count == 4)
{
fscanf(fp, "%d", &num_pt);
break;
}
else
count++;
}
int arr[num_pt][1];
while (fgets(line, sizeof line, fp) != NULL)
{
if (count == 5)
{
int k, j, cord;
for (k = 0; k < num_pt; k++)
{
for (j = 0; j < num_pt; j++)
{
while (fscanf(fp, "%d%d", &cord) > 0)
{
arr[k][j] = cord;
j++;
}
}
}
}
}
fclose(fp)
return 0;
}
After retrieving NUM_PT i tried reinitializing the count to 5 because the cordinates start from **LINE 6* in the file.
ERROR FROM COMPILER
Language: c99 ; Compiler: gcc
sample for "Storing numbers as (x, y) cordinates from a file" (It is better not to fix the reading position)
#include <stdio.h>
typedef struct point {
int x, y;
} Point;
int readPoint(FILE *fp, Point *p);
int readInt(FILE *fp, int *n);
int main(void){
FILE *fp = fopen("instance10_001.txt", "r");
Point p;
int MAX_X, MAX_Y;
readPoint(fp, &p);
MAX_X = p.x;
MAX_Y = p.y;
printf("MAX_X:%d, MAX_Y:%d\n", MAX_X, MAX_Y);
int NUM_PT;
readInt(fp, &NUM_PT);
printf("NUM_PT:%d\n", NUM_PT);
Point arr[NUM_PT];
for(int i = 0; i < NUM_PT; ++i){
readPoint(fp, &arr[i]);
printf("Point(%d, %d)\n", arr[i].x, arr[i].y);
}
fclose(fp);
}
int readLine(FILE *fp, char *buff, int buff_size){
while(fgets(buff, buff_size, fp)){
if(*buff == '#' || *buff == '\n')
continue;
return 1;
}
return 0;
}
#define LINE_MAX 128
int readPoint(FILE *fp, Point *p){
char buff[LINE_MAX];
if(readLine(fp, buff, sizeof buff)){
return 2 == sscanf(buff, "%d %d", &p->x, &p->y);
}
return 0;
}
int readInt(FILE *fp, int *n){
char buff[LINE_MAX];
if(readLine(fp, buff, sizeof buff)){
return 1 == sscanf(buff, "%d", n);
}
return 0;
}

C fork and pipe add numbers from a file

Totals different for same file when executed.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_FILE_NAME 100
#define RUNS 1
int main() {
int num,i;
FILE *fp;
char*s, buf[1024];
int count =0;
char c;
char filename[MAX_FILE_NAME];
printf("Enter filename: ");
scanf ("%s",filename);
if ((fp =fopen(filename, "r")) == NULL) {
printf("Error");
exit(1);
}
fscanf(fp,"%d",&num);
for (c = getc(fp); c!= EOF; c = getc(fp))
{
if (c == '\n'){
count = count+1;
}
}
printf("%s has %d numbers \n", filename, count);
int f;
printf("Choose from the options how many processes you want to use [1,2,4]: ");
scanf("%i", &f);
printf("%i processes \n", f);
int fds[f+1][2];
int numb[count];
int x,k;
time_t start, finish;
start = time(NULL);
for(i = 0; i < RUNS; i++)
{
pipe(fds[f]);
for( x = 0; x<f; x++)
{
pipe(fds[x]);
int ind[2];
ind[0] = ((x)*(count/f));
ind[1] = ((x+1)*(count/f));
write(fds[x][1], &ind, 2* sizeof(int));
if (fork() ==0)
{
int t =0;
int ind2[2];
read(fds[x][0], &ind2, 2*sizeof(int));
for( k = ind2[0]; k<ind2[1]; k++)
{
t += numb[k];
}
write(fds[f][1], &t, sizeof(int));
exit(0);
}
}
int m, tmp, total;
total = 0;
for( m = 0; m < f; m++)
{
for( m = 0; m < f; m++)
{
read(fds[f][0], &tmp, sizeof(int));
sleep(5);
total += tmp;
}
printf("DOne calc \n");
printf("Total: %i \n", total);
}
finish = time(NULL);
float runtime = (float)((finish-start)/RUNS);
printf("runtime: %f \n", runtime);
fclose(fp);
return 0;
}
You get random result for the same input because the calculation based on uninitialized int numb[count]; values.
According to the C99 standard, section 6.7.8.10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
Because of it int numb[count]; contains some random junk from memory. To get predictive results use explicit initialization:
#include <string.h> // memset
int numb[count];
memset (numb, 0, sizeof(numb)); // Zero-fills
Use the code bellow to put numbers from filename file into numb:
int i = 0;
char line[1024];
fseek(fp, 0, SEEK_SET);
while(fgets(line, sizeof(line), fp) )
{
if( sscanf(line, "%d", &numb[i]) == 1 ) // One number per line
{
++i;
}
}

Read file and only get integers and keep going till end

#include <stdio.h>
int getIntegers(char *filename,int a[]);
int main(void) {
/////
FILE *fp;
char file[10] = "random.txt";
fp = fopen(file, "w");
fprintf(fp, "1 2 -34 56 -98 42516547example-34t+56ge-pad12345\n");
fclose(fp);
/////
int i;
int a[100];
int n = getIntegers(file,a);
//Here i want to print out what i got from getIntegers. What it should put out = "1 2 -34 56 -98 42516547 -34 56 12345"
if (n > 0)
{
puts("found numbers:");
for(i = 0;i < n; i++)
{
printf("%d ",a[i]);
}
putchar('\n');
}
return 0;
}
int getIntegers(char *filename, int a[])
{
int c, i;
FILE *fp;
fp = fopen(filename, "r");
//I want what this code does to be done with the commented code under it. This will give "1 2 -34 56 -98 42516547"
while (fscanf(fp,"%d",&i)==1)
{
printf("%d ",i);
}
fclose(fp);
// I want this code to give "1 2 -34 56 -98 42516547 -34 56 12345"
// while ((c = fgetc(fp)) != EOF)
// {
// for(i = 0; i < c;i++)
// {
// fscanf(fp, "%1d", &a[i]);
// }
// }
// return i;
}
I have a file with numbers and words/letters in it. With this code I get the integers untill first letter, but i want to continue until EOF. And then return those numbers and print them out in main. I tried but could not get it to work. What should/could i do to get this working? Or what am I doing wrong.
Multiple issues:
int getIntegers() does not return any value. Code does not save anything in a[]. Array limits not enforced.
Commented code does not check the return value of fscanf().
Code needs to consume 1 character when fscanf() returns 0 and then try again.
When fscanf(fp, "%d", &a[i]) returns 0, it means the input is not numeric and fscanf() did not consume any of the non-numeric input. So read 1 character and try again.
#include <stdio.h>
#define N 100
int getIntegers(char *filename, int a[], int n);
int main(void) {
FILE *fp;
char file[] = "random.txt";
fp = fopen(file, "w");
if (fp == NULL) {
fprintf(stderr, "Unable to open file for writing\n");
return -1;
}
fprintf(fp, "1 2 -34 56 -98 42516547example-34t+56ge-pad12345\n");
fclose(fp);
int a[N];
int i;
int n = getIntegers(file, a, N);
puts("found numbers:");
for (i = 0; i < n; i++) {
printf("%d ", a[i]);
}
putchar('\n');
return 0;
}
int getIntegers(char *filename, int a[], int n) {
int i;
FILE *fp = fopen(filename, "r");
if (fp) {
for (i = 0; i < n; i++) {
int cnt;
do {
cnt = fscanf(fp, "%d", &a[i]);
if (cnt == EOF) { fclose(fp); return i; }
if (cnt == 0) fgetc(fp); // Toss 1 character and try again
} while (cnt != 1);
// printf("%d ", i);
}
fclose(fp);
}
return i;
}
Output
found numbers:1 2 -34 56 -98 42516547 -34 56 12345

fprintf saves wrong data to file

I have an input file a.txt:
1 abc 3
2 efgh 4.5
3 text 3
4 xyz 2
So basically, it has 3 columns, first one is int, second is text, and third is double. I need to read this file by rows (which actually works, I guess), but have some problems with writing only second and third column to another (b.txt) file. fprinft saves something like this:
0.000000
0.000000
0.000000
0.000000
xvæ$ 0.000000
instead of
abc 3
efgh 4.5
text 3
xyz 2
I simply need to save only the second and the third column from a.txt file to b.txt file. Here's my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct mypair
{
char string[1024];
double number;
} mypair;
void zero_string(char *string, int n)
{
int i;
for(i=0; i<n; i++)
string[i] = '\0';
}
int row(FILE* f, struct mypair *p)
{
int num;
if(!feof(f))
{
if(fscanf(f,"%d %s %lf", &num, p->string, &p->number) == 3)
{
return 0;
}
}
else
{
return 1;
}
}
int main(int argc, char **argv)
{
int n = 5, status = 0, i = 0, j;
struct mypair array[5];
char file_in_name[255];
char file_out_name[255];
FILE *fin;
FILE *fout;
zero_string(file_in_name, 255);
zero_string(file_out_name, 255);
printf("Data file:\n> ");
scanf("%s", file_in_name);
printf("Out file:\n> ");
scanf("%s", file_out_name);
fin = fopen(file_in_name, "r");
fout = fopen(file_out_name, "w");
if( fin == NULL )
{
exit(-1);
}
if( fout == NULL )
{
exit(-1);
}
while(status != 1)
{
status = row(fin, &array[i]);
i ++;
fprintf(fout, "%s %lf\n", array[i].string, array[i].number);
if(i >= n)
break;
}
fclose(fin);
fclose(fout);
for(j=0; j<i; j++)
printf("%s %lf\n", array[i].string, array[i].number);
return 0;
}
I modified the code, now it works, thanks!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct mypair
{
char string[1024];
double number;
} mypair;
void zero_string(char *string, int n)
{
int i;
for(i=0; i<n; i++)
string[i] = '\0';
}
int row(FILE* f, struct mypair *p)
{
int num;
if(!feof(f))
{
if(fscanf(f,"%d %s %lf", &num, p->string, &p->number) == 3)
{
return 0;
}
}
else
{
return 1;
}
}
int main(int argc, char **argv)
{
int n = 5, status = 0, i = 0, j;
struct mypair array[5];
char file_in_name[255];
char file_out_name[255];
FILE *fin;
FILE *fout;
zero_string(file_in_name, 255);
zero_string(file_out_name, 255);
printf("Data file:\n> ");
scanf("%s", file_in_name);
printf("Out file:\n> ");
scanf("%s", file_out_name);
fin = fopen(file_in_name, "r");
fout = fopen(file_out_name, "w");
if( fin == NULL )
{
exit(-1);
}
if( fout == NULL )
{
exit(-1);
}
printf("\n");
while(status != 1)
{
status = row(fin, &array[i]);
if(i >= n)
break;
else
{
if(status != -1)
fprintf(fout, "%s %lf\n", array[i].string, array[i].number);
}
i ++;
}
fclose(fin);
fclose(fout);
for(j=0; j<i; j++)
printf("%s %lf\n", array[j].string, array[j].number);
return 0;
}
In your bottom loop, you want to index your array by j, not i.

Resources