File reading with fgetc in C - c

I have a simple file reading algorithm but it's not returning the values that are in the file. The below is the code. The input txt values are 200 53 65 98 183 37 122 14 124 65 67 but the code is returning 48 48 32 53 51 32 54 53 32 57 56 32 49 56 51 32 51 55 32 49 50 50 32 49 52 32 49 50 52 32 54 53 32 54 55 -1 and I'm not sure why.
It should be taking the read in values and putting it into the linked list.
int readInputFile(char *fileName, LinkedList *list)
{
FILE *inputFile = fopen(fileName, "r");
int ch;
if (inputFile == NULL)
{
perror("Could not open file");
}
else
{
while (ch != EOF)
{
ch = fgetc(inputFile);
printf("%d", ch);
if (ferror(inputFile))
{
perror("Error reading from source file.");
}
else
{
//printf("%d", ch);
insertLast(list, ch);
}
}
}
}

Your code has undefined behavior because you test while (ch != EOF) with ch uninitialized the first time. You should write:
while ((ch = fgetc(inputFile)) != EOF) {
[...]
Yet the problem is you read individual bytes instead of parsing the file contents for numbers expressed as decimal integers. You should use fscanf() to convert the text into integers.
You also forgot to close the file, causing resource leakage.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int readInputFile(const char *fileName, LinkedList *list)
{
FILE *inputFile = fopen(fileName, "r");
if (inputFile == NULL) {
fprintf(stderr, "Could not open file %s: %s\n",
fileName, strerror(errno));
return -1;
} else {
int value, count = 0;
char ch;
while (fscanf(inputFile, "%d", &value) == 1) {
printf("inserting %d\n", value);
insertLast(list, value);
count++;
}
if (fscanf(inputFile, " %c", &ch) == 1) {
fprintf(stderr, "File has extra bytes\n");
}
fclose(inputFile);
return count; // return the number of integers inserted.
}
}

You read a character with fgetc() but you want to read a number which you do with int d; fscanf(inputFile, "%d", &d).

Related

Writing half of an int array into a new text file

In my program, I am trying to opens the text file provided at the command-line, and then creates two new text files values1.txt and values2.txt. The file from the command line contains 100 unique integer numbers. Half of the numbers are copied into values1.txt, the other half is copied into values2.txt.
However, when I tried to do it for values1.txt, I got the following values:
101
32758
0
0
176197744
32764
3
0
176197728
32764
0
0
-78325960
32758
0
0
1
0
-78326000
32758
0
0
1700966438
0
-78325096
32758
176197896
32764
176197952
32764
-78326000
32758
0
0
-80547345
32758
0
0
176197952
32764
0
0
0
0
0
0
-78326000
32758
-82942073
32758
8
Here is my code:
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
int cfileexists(const char * filename){
/* try to open file to read */
FILE *file;
if (file = fopen(filename, "r")){
fclose(file);
return 1;
}
}
int main(int argc,char*argv[]){
char *p= argv[1];
int numArray[100];
int i=0;
int sum1arr[50];
int sum2arr[50];
if (! cfileexists(p)){
printf("Error, unable to locate the data file %s\n", p);
return 100;
}
for(i;i<100;i++){
FILE *stream=fopen(p,"r");
while(!feof(stream)){
fscanf(stream,"%d",&numArray[i]);
}
FILE * fPtr = NULL;
fPtr = fopen("values1.txt", "w");
for(int j=0;j<50;j++){
fprintf(fPtr,"%d\n",numArray[j]);
}
}
}
For comparison; this is the source txtfile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
The for statement has too many cycles, you should use the read cycle to also write, you also can use fscanf return to verify whe the file reaches it's end. If you don't need to save the values you can even use on singe int to temporarily store the value till it's written.
Here is a possibe implementation with comments:
Live demo
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cfileexists(const char *filename)
{
/* try to open file to read */
FILE *file;
if ((file = fopen(filename, "r")))
{
fclose(file);
return 1;
}
return 0; //return 0 if file not found
}
int main(int argc, char *argv[])
{
if(argc != 2){ //check number of arguments
puts("Wrong number of arguments");
return(EXIT_FAILURE); //EXIT_FAILURE macro is more portable
}
FILE *stream;
FILE *fPtr = NULL;
FILE *fPtr2 = NULL;
int numArray[100];
int i = 0;
fPtr = fopen("values1.txt", "w");
fPtr2 = fopen("values2.txt", "w");
//you can use fopen to check file nstead of the
//function, it returns null if no file is opened
if (!(stream = fopen(argv[1], "r")))
{
perror("Error, unable to locate the data file"); //also prints error signature
return EXIT_FAILURE;
}
//check input, stop when there is nothing else to read
while (fscanf(stream, "%d", &numArray[i]) == 1 && i < 100)
{
if(i < 50)
fprintf(fPtr, "%d\n", numArray[i]); //write to file 1
else
fprintf(fPtr2, "%d\n", numArray[i]); //write to file 2
i++;
}
fclose(stream);
fclose(fPtr);
fclose(fPtr2);
}
Here's a different approach that uses getline():
#include <stdio.h>
#include <stdlib.h>
#define SPLIT_POINT 50
int main(void) {
char filename[] = "test";
FILE *fp = fopen(filename, "r");
if (!fp) {
fprintf(stderr, "Couldn't open %s\n", filename);
}
// Check file open (as above) left out for brevity
FILE *out1 = fopen("values1.txt", "w");
FILE *out2 = fopen("values2.txt", "w");
char *line = NULL;
size_t n = 0, i = 0;
ssize_t len = 0;
while ((len = getline(&line, &n, fp)) != EOF) {
// Select which output file to write to
FILE *out = i < SPLIT_POINT ? out1 : out2;
// getline includes the newline - remove this
if (i == SPLIT_POINT - 1 && len > 0) {
line[--len] = 0;
}
// Write to the relevant output file
fprintf(out, "%s", line);
i++;
}
fclose(fp);
fclose(out1);
fclose(out2);
free(line);
return 0;
}
If you don't care about removing newlines, you could simplify the getline() call - just don't bother with the len variable.

Read numbers from txt file second line in a C Array

I do have a txt file which looks like this
10
41 220 166 29 151 47 170 60 234 49
How can I read only the numbers from the second row into an array in C?
int nr_of_values = 0;
int* myArray = 0;
FILE *file;
file = fopen("hist.txt", "r+");
if (file == NULL)
{
printf("ERROR Opening File!");
exit(1);
}
else {
fscanf(file, "%d", &nr_of_values);
myArray = new int[nr_of_values];
// push values from second row to this array
}
How can I read only the numbers from the second row into an array in C?
Ignore the first line by reading and discarding it.
You could use something like that:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char const *filename = "test.txt";
FILE *input_file = fopen(filename, "r");
if (!input_file) {
fprintf(stderr, "Couldn't open \"%s\" for reading :(\n\n", filename);
return EXIT_FAILURE;
}
int ch; // ignore first line:
while ((ch = fgetc(input_file)) != EOF && ch != '\n');
int value;
int *numbers = NULL;
size_t num_numbers = 0;
while (fscanf(input_file, "%d", &value) == 1) {
int *new_numbers = realloc(numbers, (num_numbers + 1) * sizeof(*new_numbers));
if (!new_numbers) {
fputs("Out of memory :(\n\n", stderr);
free(numbers);
return EXIT_FAILURE;
}
numbers = new_numbers;
numbers[num_numbers++] = value;
}
fclose(input_file);
for (size_t i = 0; i < num_numbers; ++i)
printf("%d ", numbers[i]);
putchar('\n');
free(numbers);
}

Reading from file in C including char and integer

How to read and store each column in the following text from a file into an array
A17ke4004 44 66 84
A17ke4005 33 62 88
A17ke4008 44 66 86
The first column should be string and the rest should be integer
Here is a simple code that do the job.
First put your text inside a test.txt file, save it in C source code path.
test.txt
A17ke4004 44 66 84
A17ke4005 33 62 88
A17ke4008 44 66 86
Code
#include <stdio.h>
int main (void)
{
FILE *fp = NULL;
char *line = NULL;
size_t len = 0;
size_t read = 0;
char string[10][32];
int a[10], b[10], c[10];
int count = 0;
fp = fopen("test.txt", "r");
if(fp != NULL){
while((read = getline(&line, &len, fp)) != -1){
sscanf(line, "%s%d%d%d", string[count], &a[count], &b[count], &c[count]);
printf("<%s> - <%d> - <%d> - <%d>\n", string[count], a[count], b[count], c[count]);
count++;
}
}else{
printf("File can't open\n");
}
return 0;
}
Compile, Run
gcc -Wall -Wextra te.c -o te
./te
If you have more than 10 lines you should increase the arrays dimension.
Hope this help you.

Parsing and splitting a string from txt file in C

I'm new into C and I got an assignment to read line by line from .txt file and parse some strings into matrix where first line is first row, second line is second row etc. This is what I have in my text.txt file:
07 45 C4 16 0F 02 19 0I 17 0G
09 45 C4 15 0E 03 11 0A 12 0B 13 0C
13 45 C4 13 0C 03 19 0I 11 0A 17 0G 14 0D 16 0F
05 45 C4 18 0H 01 12 0B
This is what I was able to do so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *Read(char filename[]);
void split(char *content);
int main(void){
char filename[] = "text.txt";
char *content = Read(filename);
split(content);
return 0;
}
char *Read(char filename[]){
char *buffer;
long size;
FILE *log = fopen("text.txt", "r");
fseek(log, 0, SEEK_END);
size = ftell(log);
rewind(log);
buffer = (char*) malloc(sizeof(char) * size);
fread(buffer, 1, size, log);
fclose(log);
return buffer;
}
void split(char *content){
char *buffer = strtok(content, " ");
while(buffer != NULL){
printf("%s\n", buffer);
buffer = strtok (NULL, " ");
}
}
I would really appreciate comments in code because I'm rookie and it would help me to better understand some things.
To give you an idea of how it works, I wrote this snippet which manually read the line in that array, supposing that we already know the desired results.
The following approach cannot be considered the right one. Ideally you would have a series of rules to split the string, in the following however you have to set the scanf format manually for each line that you want to read.
Remember to check the return value of scanf, here we should ensure that we have read 7 elements.
int main(void) {
FILE *log;
char buffer[SIZE];
char line[SIZE];
char array[10][10];
if ((log = fopen("text.txt", "r")) == NULL){
fprintf(stderr, "Can't open input file!\n");
return(1);
}
while(fgets(buffer, sizeof(buffer), log)){
int ret = sscanf(buffer, "%2s%2s%2s%4s%2s%4s%4s", array[0], array[1], array[2], array[3], array[4],array[5], array[6]);
printf("read %d elements\n", ret);
if (ret != 7) {
return(1);
}
printf("%s", buffer);
}
int i;
for (i=0; i < 6; i++)
printf("%s\n", array[i]);
fclose(log);
return 0;
}

C- Run-length encoding doesn't work on large file, worked on smaller file

I have a problem, when I use this on a 41 kb file it compressed (Although because it uses run-length encoding it always seems to double the size of the file) and decompresses properly. However when I tried to use it on a 16,173 kb file and I decompressed it, it didn't open and the file size was 16,171 kb....so it decompressed it but it didn't return back to it's original form....something screwed up....Has me baffled, I just can't seem to figure out what I am doing wrong....
The method used is run-length encoding, it replaces every byte with a count followed by the byte.
Before:
46 6F 6F 20 62 61 72 21 21 21 20 20 20 20 20
After:
01 46 02 6F 01 20 01 62 01 61 01 72 03 21 05 20
Here is my code:
void compress_file(FILE *fp_in, FILE *fp_out)
{
int count, ch, ch2;
ch = getc(fp_in);
for (count = 0; ch2 != EOF; count = 0) {
// if next byte is the same increase count and test again
do {
count++; // set binary count
ch2 = getc(fp_in); // set next variable for comparison
} while (ch2 != EOF && ch2 == ch);
// write bytes into new file
putc(count, fp_out);
putc(ch, fp_out);
ch = ch2;
}
fclose(fp_in);
fclose(fp_out);
fprintf(stderr, "File Compressed\n");
}
void uncompress_file(FILE *fp_in, FILE *fp_out)
{
int count, ch, ch2;
for (count = 0; ch2 != EOF; count = 0) {
ch = getc(fp_in); // grab first byte
ch2 = getc(fp_in); // grab second byte
// write the bytes
do {
putc(ch2, fp_out);
count++;
} while (count < ch);
}
fclose(fp_in);
fclose(fp_out);
fprintf(stderr, "File Decompressed\n");
}
You miss to check your run length count for char overflow, so this will go wrong if you have more than 255 identical characters in your file in sequence.
Here is the working source code:
// Chapter 22 Programming Project #7
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
void compress_file(FILE *fp_in, FILE *fp_out);
void uncompress_file(FILE *fp_in, FILE *fp_out);
int main(void)
{
FILE *fp_in, *fp_out;
char nm_in[FILENAME_MAX], nm_out[FILENAME_MAX];
int chk;
for (;;) {
printf(" ----------------------------------------- \n");
printf("| 1 - Compress |\n");
printf("| 2 - Decompress |\n");
printf("| 3 - Exit |\n");
printf(" ----------------------------------------- \n");
do {
printf("Enter a command: ");
scanf(" %d", &chk);
} while (isalpha(chk));
if (chk == 3)
exit(EXIT_SUCCESS);
printf("Enter input file name: ");
scanf(" %s", nm_in);
printf("Enter output file name: ");
scanf(" %s", nm_out);
// Open file to read from
while ((fp_in = fopen(nm_in, "rb")) == NULL) {
fprintf(stderr, "Can't open \"%s\"\n", nm_in);
printf("Enter input file name: ");
scanf(" %s", nm_in);
}
// Open file to write to
while ((fp_out = fopen(nm_out, "wb")) == NULL) {
fprintf(stderr, "Can't create \"%s\"\n", nm_out);
printf("Enter output file name: ");
scanf(" %s", nm_out);
}
switch(chk) {
case 1: compress_file(fp_in, fp_out); break;
case 2: uncompress_file(fp_in, fp_out); break;
}
putchar('\n');
}
return 0;
}
void compress_file(FILE *fp_in, FILE *fp_out)
{
int count, ch, ch2, chk;
ch = getc(fp_in);
ch2 = ch;
while (ch2 != EOF) {
// if next byte is the same increase count and test
for (count = 0; ch2 == ch && count < 255; count++) {
ch2 = getc(fp_in); // set next variable for comparison
}
// write bytes into new file
putc(count, fp_out);
putc(ch, fp_out);
ch = ch2;
}
fclose(fp_in);
fclose(fp_out);
fprintf(stderr, "File Compressed\n");
}
void uncompress_file(FILE *fp_in, FILE *fp_out)
{
int count, ch, ch2;
for (count = 0; ch2 != EOF; count = 0) {
ch = getc(fp_in); // grab first byte
ch2 = getc(fp_in); // grab second byte
// write the bytes
do {
putc(ch2, fp_out);
count++;
} while (count < ch);
}
fclose(fp_in);
fclose(fp_out);
fprintf(stderr, "File Decompressed\n");
}

Resources