I am trying to take all the integers from the file file.txt and place them in a dynamically allocated array. However the file could also contain other characters, and these should not be put in the array.
The file contains the following:
2 -34 56 - 23423424
12example-34en+56ge-tal345
int* getIntegers(char* filename, int* pn)
{
FILE* fileInput = fopen(filename, "r");
int* temp = (int*)malloc( 100*sizeof(int));
int counter = 0;
int c= fgetc(fileInput);
while(c != EOF){
counter ++;
printf("%d;\t%d\n", counter, c);fflush(stdout);
temp[counter++] = c;
}
*pn = counter;
return (temp);
}
int main(void)
{
int n;
int* a = getIntegers("file.txt", &n);
if (a != NULL){
puts("numbers found:");
for (int i = 0;i < n; i++){
printf("%d ",a[i]);
}
free(a);
}
putchar('\n');
while(getchar()== '\n');
return (EXIT_SUCCESS);
}
when I run this the following output is returned:
Output:
1; 49
3; 49
5; 49
7; 49
9; 49
11; 49
13; 49
15; 49
17; 49
19; 49
21; 49
While the correct output should have been
found numbers:
12 -34 56 23423424 12 -34 56 345
There are many things wrong with that program.
You leak your file object. You should close it with fclose() when done.
If there are more than 100 numbers in your input, you will overflow your buffer, trash your stack, and do Bad Things to your program.
You increment your counter twice at every loop iteration, so you'll skip every second entry in your output array.
You never read another byte from the input, so you're just going to keep processing the same byte over and over in an infinite loop until your buffer overflow causes your program to crash.
You never convert the digits that you read from your input file into an integer; instead, you just take the character code. 49 is the ASCII/UTF-8 code for '1', which appears to be the first character in your input.
try this
#include <stdlib.h>
#include <stdio.h>
int* getIntegers(char* filename, int* pn)
{
int* temp = (int*)malloc( 100*sizeof(int));
int counter = 0;
int result;
int c;
FILE* fileInput = fopen(filename, "r");
if ( fileInput == NULL) {
return temp; // return if file open fails
}
while( 1) {
result = fscanf (fileInput, "%d", &c);//try to read an int
if ( result == 1) { // read successful
temp[counter] = c; //save int to array
counter++;
printf("%d;\t%d\n", counter, c);
}
else { // read not successful
fscanf ( fileInput, "%*[^-+0-9]"); //scan for anything not a -, + or digit
}
if ( counter > 98) { // dont exceed array
break;
}
if ( feof( fileInput)) { // check if at end of file
break;
}
}
fclose ( fileInput); // close the file
*pn = counter;
return (temp);
}
int main(void)
{
int n;
int i;
int* a = getIntegers("file.txt", &n);
if (a != NULL){
printf("numbers found:");
for (i = 0;i < n; i++){
printf("%d ",a[i]);
}
free(a);
}
putchar('\n');
return (EXIT_SUCCESS);
}
Many loop holes in your code.You need to first fix it.
int c= fgetc(fileInput);
while(c != EOF)
{
counter ++;
printf("%d;\t%d\n", counter, c);fflush(stdout);
temp[counter++] = c;
}
This code make me crazy. What you gain by reading only one character from file and run while loop? Give chance to read another byte.
Must check the return value fopen function. what if files not present OR error in opening? Your program gone wild. So ensure
FILE* fileInput = fopen(filename, "r");
if(fileInput==NULL ){
printf("Error to open file\n");
return
}
Also you incremented counter two times in loop first one is counter ++; and second one is temp[counter++] = c; this is wrong to manage array index.
Also most important thing is every open file must be close.
Related
So I need output size of array in this file text and to do this I must break the loop in the last position by using NULL to break but the problem here that when arr[i] come to value 0, it equal to NULL and break at that position so my size of array is not complete. How to resolve it? Thanks for support!
The file .txt input:
3
4
0
5
6
The code:
#include <stdio.h>
int main() {
char a[20];
char e[40];
int arr[30];
int num, key, k = 0, len = 0;
printf("Enter a filename: ");
scanf("%s", &a);
scanf("%c", &e);
FILE* rfile;
rfile = fopen(a, "r");
if (rfile == NULL) {
printf("Not found the file !!!");
}
else {
printf("Successfully accessed the file: %s\n", a);
int i;
for (i = 0; i < 30; i++) {
fscanf(rfile, "%d", &arr[i]);
fscanf(rfile, "%c", &e);
if (arr[i] == NULL) { // PROBLEM HERE
break;
}
len++;
}
}
printf("The size of array: %d", len);
return 0;
}
You can find some more details regarding what NULL is here, but you should save NULL for pointer comparisons, not comparing against ints as you are doing. In fact, your usage generates a warning:
warning: comparison between pointer and integer
Despite that, 0 == NULL will evaluate to true. Since 0 is in your list of values, you prematurely break revealing your problem. Instead, you simply need to read the entire file, either until you run out of room in your array (already covered by your for loop) or reach the end of the file (designated by EOF). To determine that, you need to check the return value of fscanf. Below is an example of a possible implementation:
#include <stdio.h>
#include <stdlib.h>
int main() {
int arr[30];
int len = 0;
FILE* rfile;
rfile = fopen("file.txt", "r");
if (rfile == NULL) {
printf("Not found the file !!!");
exit(-1);
}
else {
int i;
for (i = 0; i < 30; i++) {
// fscanf returns the number of correctly matched items, or
// EOF when the end of the file is reached (or EOF on error)
int ret = fscanf(rfile, "%d", &arr[i]);
// did we get a correct match?
if (ret == 1)
{
// we matched one number as expected, increment len
len++;
}
// did we reach the end of file?
else if (ret == EOF)
{
// EOF can also indicate an error, check errno here to determine if
// an error occurred instead of end of file, if you want
break;
}
}
}
// prints 5 with your input file example
printf("The size of array: %d\n", len);
return 0;
}
I have no idea what you were trying to accomplish with e, so I removed that as well as other unused variables, and hardcoded user input.
arr is the array of ints arr[i] has type int. NULL is a pointer.
If 0 indicated the end of the data (sentinel value) then:
if (arr[i] == 0) break;
or in a short form
if (!arr[i]) break;
I would like to read 3-digit-numbers with spaces inbetween from a file with the fgetc()-command and put them into an array, which is not currently working, as the resulting array has completely different objects in it. What am I doing wrong? (I used a file with "107 313 052 614" in it, resulting in the output "5435 5641 5380 5942")
My Code:
#include<stdio.h>
#include<stdlib.h>
void print_array(int* arrayp, int lengthp){
int i;
for(i=0;i<lengthp;i++){
printf("%i ", arrayp[i]);
}
return;
}
int main(){
int length=1;
int i;
FILE *fp1;
fp1 = fopen("durations.txt", "r");
fgetc(fp1);fgetc(fp1);fgetc(fp1);
while(fgetc(fp1)!=EOF){
length++;
fgetc(fp1);
fgetc(fp1);
fgetc(fp1);
}
fclose(fp1);
int* list = (int*) malloc(sizeof(int)*length);
FILE *fp2;
fp2 = fopen("durations.txt", "r");
for(i=0;i<length;i++){
list[i]=0;
list[i]+=100*(fgetc(fp2));
list[i]+=10*(fgetc(fp2));
list[i]+=(fgetc(fp2));
fgetc(fp2);
}
fclose(fp2);
print_array(list, length);
return 0;
}
The characters that are used to store digits in a "readable" file are not "numbers". The most popular encoding is ascii character encoding, ex. the 1 digit is represented with the number 49 in decimal.
Because the 0, 1, 2 ... 9 digits in ascii encoding are encoded in increasing order, you can just substract 48 (ie. '0' character) to convert a digit character to it's machine format Just - '0'.
Change you loop into:
for(i=0;i<length;i++){
list[i]=0;
list[i]+=100*(fgetc(fp2) - '0');
list[i]+=10*(fgetc(fp2) - '0');
list[i]+=(fgetc(fp2) - '0');
fgetc(fp2);
}
This also explains the current output of your program. If you don't substract '0' from the numbers, then for example for 107 you get:
100 * '1' + 10 * '0' + '7' =
100 * 49 + 10 * 48 + 55 =
5435
The 49, 48 and 55 are decimal values for digits 1, 0 and 7 in ascii table.
The problem is that your are reading in the (probably) ASCII values of each digit and assuming that is the value of the digit. You need to subtract the value of the zero character from each value, like this:
for (i = 0; i < length; i++) {
list[i] = 0;
list[i] += 100 * (fgetc(fp2)-'0');
list[i] += 10 * (fgetc(fp2)-'0');
list[i] += (fgetc(fp2)-'0');
fgetc(fp2);
}
This will work even if your system doesn't use ASCII encoding.
It might be simpler to just read the numbers into cstrings then use the stdlib function atoi to convert each string to a number before loading into the array of ints:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
//open the file for reading with error checking:
FILE* fp;
char c = '0';
int length = 0;
fp = fopen("durations.txt", "r");
if (fp == NULL) {
printf("Could not open file\n");
return 0;
}
//count the number of lines in a EOF-terminated string w/o newlines
for (c = fgetc(fp); c != EOF; c = fgetc(fp)) {
if (c == ' ') {
length += 1;
}
}
rewind(fp); //go back to file end w/o needing close/open
//Then, assuming only spaces are between numbers (so length = length + 1)
char buffer[4];
int* lst = (int*) malloc(sizeof(int)*length);
for (int i = 0; i < length + 1; i++) {
fscanf(fp, "%s", buffer); //stops at spaces
lst[i] = atoi(buffer);
}
//close the file with error checking
int check = fclose(fp);
if (check != 0) {
printf("File close failed");
return 0;
}
for (int i = 0; i < length + 1; i++) { //print result
printf("%d\n", lst[i]);
}
free(lst); //clean up memory after use
lst = NULL;
return 0;
}
It seems like I didn't quite understand how the file stream works. My text file right now contains the following integers: 1 10 5 4 2 3 -6, but I would like the program to be able to read any number of integers from the file, should it change.
Apparently I'm not even using the correct functions.
The code I have written is the following:
int main() {
printf("This program stores numbers from numeri.txt into an array.\n\n");
int a[100];
int num;
int count = 0;
FILE* numeri = fopen("numeri.txt", "r");
while (!feof(numeri)) {
num = getw(numeri);
a[count] = num;
if (fgetc(numeri) != ' ')
count++;
}
int i;
for (i = 0; i < count; i++) { printf("%d ", a[i]); }
return 0;
}
I would like it to print out the array with the stored numbers, but all I get is: 540287029 757084960 -1
Can someone help me understand what I did wrong and maybe tell me how to write this kind of code properly?
I have fixed your code based on comments. I used fscanf to read from file and limited the amount of numbers that can be stored in array by checking count < 100 and checking whether fscanf filled exactly one argument.
Also, I checked that whether file could be opened or not, just for safety. If it couldn't be opened, then just print error message and return 1.
int main() {
printf("This program stores numbers from numeri.txt into an array.\n\n");
int a[100] = {0};
int num;
int count = 0;
int i = 0;
FILE* numeri = fopen("numeri.txt", "r");
if (numeri == NULL) {
printf("Can't open file\n");
return 1;
}
while (count < 100 && fscanf(numeri, "%d", &num) == 1) {
a[count++] = num;
}
for (i = 0; i < count; i++) { printf("%d ", a[i]); }
return 0;
}
i have a file like that :
1 100
2 200
3 300
4 400
1
i want to save it as a matrix and i want to save NULL if there is no second number !
i tried to write the program but it does not work correctly !
#include<stdio.h>
int main() {
int k=0 ,i,j , arr[100][100];
FILE *in= fopen("file.txt","r");
char line[1000];
while(fgets(line,1000,in) !=NULL) k++;
fgets(line,1000,in);
for (i=0;i<k;i++){
for (j=0;j<2;j++){
int tmp ;
fscanf(in ,"%d", &tmp) ;
arr[i][j] = tmp ;
}
}
fclose(in);
return 0; }
Two major problems:
The first is that the first loop will read all lines, even the one with the single number on the line. That means the lonely fgets call will not do anything, and more importantly that the value of k will be wrong.
The second problem is that once you read all data from the file, you don't go back to the beginning of the file, instead you continue to try and read from beyond the end of the file.
The first problem can be solve by skipping the second fgets call, and decreasing k by one.
The second problem can be solved by calling rewind after you counted the number of lines.
Also when you actually read the numbers, you don't need the inner loop, just do e.g.
scanf("%d %d", &arr[i][0], &arr[i][1]);
Actually, you don't need the first line-counting loop at all, you can do it all in a single loop, by using fgets and sscanf and then checking the return value of sscanf. So your program could look something like
#include <stdio.h>
int main(void)
{
int values[100][2];
FILE *input = fopen("file.txt", "r");
size_t entries = 0;
if (input != NULL)
{
char buffer[40];
while (fgets(buffer, sizeof(buffer), input) != NULL && entries < 100)
{
int res = sscanf(buffer, "%d %d", &values[entries][0], &values[entries][1]);
if (res <= 1 || res == EOF)
{
// Read the last line with only one number, or an error happened
values[entries][0] = 0;
values[entries][1] = 0;
break;
}
++entries;
}
if (ferror(input))
{
printf("Error reading file\n");
}
fclose(input);
}
// All done, the number of "records" or "entries" is in the variable entries
// Example code: print the values
for (size_t i = 0; i < entries; ++i)
printf("Line %d: %d %d\n", i + 1, values[i][0], values[i][1]);
return 0;
}
I have a textfile of numbers written in words, with spaces between like..
zero three five two one .. etc there are 3018 words in total.
This is my code:
#include <stdio.h>
int main(void)
{
int i = 0;
int d = 0;
int j = 0;
char array[9054][5];
char hi[9054];
FILE *in_file;
in_file = fopen("message.txt", "r");
while (!feof(in_file))
{
fscanf(in_file, "%s", array[i]);
i++;
}
printf(array[9049]);
while (1);
return 0;
}
so the 9049th worth in my textfile is the number three.. but when I run this script, it prints "threethreezero"instead?? i thought the fscanf ignored whitespace (spaces) so why does accept another three and zero into this string?
OP figured things out with the help of comments, so here is a cumulative fix.
#include <stdio.h>
int main(void)
{
int i = 0;
int d = 0;
int j = 0;
// Make room for the null character
char array[9054][5+1];
char hi[9054];
FILE *in_file;
in_file = fopen("message.txt", "r");
//check `fscanf()`'s return value rather than using feof()
// Limit input put with 5
while (fscanf(in_file, "%5s", array[i]) == 1);
i++;
}
// Check that code read enough input
if (i >= 9049) {
// Do not use `printf()` on uncontrolled strings that may contain %
fputs(array[9049], stdout);
} else {
puts("Oops");
}
while (1);
return 0;
}