I am building a C program which gets a .txt file as an argument. Inside the .txt there are rows of integer numbers, with a space between them, like this:
1 2 3 4
5 6 7 8
...
I am supposed to find out, if a non-integer-character shows up inside the .txt file, like this:
1 2 a 4
...
Since there is no instanceof operator in C, I use an array which contains the numbers from 0-9 and check each character of the .txt-file, if it is either a space or an integer. If it is neither, the program is supposed to exit. If there are no problems in the file, the program calculates a median and prints the line to stdout. This is my code:
#include <stdio.h>
#include <ctype.h>
int arrayContains(char value);
int main(int argc, char **argv) {
const int LINESIZE = 255;
if (argc != 2) {
printf("wrong args!");
return -1;
}
char *command1 = argv[1];
FILE *handle = fopen(command1, "r");
if (!handle) {
printf("file not found!");
return -1;
}
int count = 0;
int sum = 0;
int median;
char string[LINESIZE];
while (fgets(string, LINESIZE, handle) != NULL) {
for (int i = 0; i <= sizeof(string) / sizeof(string[0]) - 1; i++) {
printf("%c", string[i]);
if (string[i] == ' ') {
i++;
}
else if (arrayContains(string[i]) == 0) {
count++;
sum += (int)string[i];
}
else {
printf("non-integer-character found!\n");
return -1;
}
}
median = sum / count;
printf("%s\n", string);
printf("%d\n", median);
}
}
int arrayContains(char value) {
const char numbers[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
for (int i = 0; i <= 9; i++) {
if (numbers[i] == value) {
return 0;
}
}
return -1;
}
Now the output of the program is always the first number of the txt-file and immediately after that: "non-integer-character found!". Which tells me that the comparison between the element of the string from gets() and an element from the constant "numbers" array inside the arrayContains() function, will always result in a return of -1 from the arrayContains() function. What am I doing wrong?
There are several problems with your code.
This bit matches a space, but will result in you skipping the following character because your loop will also do i++
.
if (string[i] == ' ') {
i++;
}
This is not the right way to turn a digit into a number. What you're getting here is the ASCII value of the character rather than the value of the digit. So for example if you have a '1' you're adding 49 to sum rather than 1.
sum += (int)string[i];
As discussed elsewhere, you're better off using isdigit()
to identify if you've got a digit character. You can also use isspace()
to test to see if you have a space or '\n' character (it covers all whitespace). Which would make your loop statement a lot less complicated as you can process the whole string and easily handle lines that are longer than the size of your buffer.
This code corrects the problems you have
while (fgets(string, LINESIZE, handle) != NULL) {
for (char *pos=string; *pos!='\0'; pos++) {
printf("%c", *pos);
if (isdigit(*pos)) {
count++;
sum += *pos-'0';
} elseif(!isspace(*pos)) {
printf("non-integer-character found!\n");
return -1;
}
}
median = sum / count;
printf("%s\n", string);
printf("%d\n", median);
}