Reading from file C programing - c

I'd appreciate any help I can get. I'm not sure I completely understand this program. I also get the following errors when I try to run it.
I was also told that on line 15 I was trying to mod a char array. What should I be doing? Thanks for taking a look.
structFinal.c: In function print_part':
structFinal.c:14: error: invalid operands to binary %
structFinal.c: In function main':
structFinal.c:36: error: syntax error before ']' token
#include <stdio.h>
#define NAME_LEN 25
typedef struct {
int number;
char name[NAME_LEN+1];
int on_hand;
} part;
void print_part(part p[], int ind) {
int i;
printf("Whole List\n");
for(i = 0; i< ind; i++)
{
if(p[ind].name % 2 == 0)
printf("Part number: %d\n", p[ind].number);
printf("Part name: %s\n", p[ind].name);
if(p[ind].on_hand < 5)
printf("Quantity on hand: %d\n", p[ind].on_hand);
}
printf("%d\n", p[ind].number);
fgets(p[ind].name,50,fp);
fscanf(fp, "%d", &p[ind].on_hand);
printf("%s\n----%d\n", p[ind].name, p[ind].on_hand);
ind++;
fscanf(fp, "%d", &p[ind].number);
a = fgetc(fp);
} print_part(p[ ] , ind);
fclose(fp);
return 0;
Edit: I just tried this on my Ubuntu machine in Netbeans and it ran. We're suppose to run this in Unix and that's were it fails. I'm lost.
Edit: This is my final file so far. I'm pretty sure this works.
#include <stdio.h>
#define NAME_LEN 25
typedef struct {
int number;
char name[NAME_LEN+1];
int on_hand;
} part;
void print_part(part p[], int ind) {
int i;
printf("Whole List\n");
for(i = 0; i< ind; i++)
{
printf("Part number: %d\n", p[i].number);
printf("Part name: %s\n", p[i].name);
printf("Quantity on hand: %d\n", p[i].on_hand);
}
}
int main() {
/* first try, input only one set and print it */
part p[50];
int ind=0;
FILE *fp;
fp = fopen("structTest.txt", "r");
fscanf(fp, "%d", &p[ind].number);
char a;
a = fgetc(fp); /* extract the return symbol out of input buffer */
while (p[ind].number != 0)
{
while (a != '\n')
{
a = fgetc(fp);
}
printf("%d\n", p[ind].number);
fgets(p[ind].name,50,fp);
fscanf(fp, "%d", &p[ind].on_hand);
printf("%s\n----%d\n", p[ind].name, p[ind].on_hand);
ind++;
fscanf(fp, "%d", &p[ind].number);
a = fgetc(fp);
}
print_part(p , ind);
fclose(fp);
return 0;
}
/*
the code is fixed so it will extact all white spaces after a part number
is typed. the getchar while loop will keep get one character to var a
until a return key is reached
*/

Here you have some character at the end. Notices this ` which doesn't belong there?
if(p[ind].name % 2 == 0)`
And this
print_part(p[ ] , ind);
should be
print_part(p , ind);

p[ind].name is a characters array, you cannot run modulu operation on it.
You can run % on numbers - integers.
What would a logical meaning be of doing module on a string? (char array)
Say you have the array contents of abcde what is abcde % 2?

Related

Why my fscanf does not read the first string but reads the last line into the first string instead?

I'm a beginner at files including code so please someone help me. This is what my code looks like.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define first_ten_hours 7.99;
#define after_ten_hours 1.99;
double charges_all(int hour);
double charges_avg(int money, int hour_use);
double round_money(double sum);
int main()
{
FILE *f_read, *f_write;
f_read = fopen("usage.txt", "r");
f_write = fopen("charges.txt", "w");
if(f_read == NULL)
{
printf("Error to open the file.\n");
return 1;
}
char date[2][10];
char studenid[10][100];
double using_hour[10];
int current_line = 1;
for(int i = 0; i < 11; i++)
{
if(current_line == 1)
{
fscanf(f_read, "%s %s", date[0], date[1]);
current_line++;
}
else
{
fscanf(f_read, "%s %lf", studenid[i], &using_hour[i]);
current_line++;
}
}
current_line = 1;
for(int i = 0; i < 11; i++)
{
if(current_line == 1)
{
printf("%s %s\n", date[0], date[1]);
current_line++;
}
else
{
printf("%s %lf\n", studenid[i], using_hour[i]);
current_line++;
}
}
fclose(f_read);
fclose(f_write);
return 1;
}
After the current_line = 1;, I print to check and see the problem.
This is my text file.
12 2022
18010 4.5
92052 3.2
01051 7.4
11052 6.3
13052 5.5
01081 2.2
65052 1.3
94052 2.8
32052 3.7
41051 4.9
and this is the output from the printf loop:
41051 2022
18010 4.500000
92052 3.200000
01051 7.400000
11052 6.300000
13052 5.500000
01081 2.200000
65052 1.300000
94052 2.800000
32052 3.700000
41051 4.900000
But what I want is for the first string at the first line to be 12.
Because of the way you have written your for loop(s), you are accessing elements of the studenid and using_hour arrays that are out-of-bounds on the last iteration of those loops (i.e. when i is 10 – an element at [10] is past the end of an array declared with 10 elements). Such "bad access" causes undefined behaviour, which may (as it appears in your case) include overwriting the value you had previously read into the date array elements.
A "quick fix" is to change the [i] indexes (all of them) to [i - 1]. However, a better way would be to put the read of the first line outside the loops and then run those loops for the next 10 lines:
int main()
{
FILE* f_read, * f_write;
f_read = fopen("usage.txt", "r");
f_write = fopen("charges.txt", "w");
if (f_read == NULL)
{
printf("Error to open the file.\n");
return 1;
}
char date[2][10];
char studenid[10][100];
double using_hour[10];
fscanf(f_read, "%9s %9s", date[0], date[1]); // Read first line differently
for (int i = 0; i < 10; i++) // Run the loop ONLY 10 times ...
{
fscanf(f_read, "%99s %lf", studenid[i], &using_hour[i]);
}
printf("%s %s\n", date[0], date[1]);
for (int i = 0; i < 10; i++)
{
printf("%s %lf\n", studenid[i], using_hour[i]);
}
fclose(f_read);
fclose(f_write);
return 1;
}

I have problem with reading input with blank spaces

I made this function to get input:
void entrada_dados(Time* time, int i){
scanf("%s %d %d", time[i].nome, &time[i].gols_marcados, &time[i].gols_sofridos);
};
The input is in this form:
2
Campinense
23
12
ABC
30
13
The main is:
int main(void) {
int n = 0;
scanf("%d", &n);
for(int i = 0; i < n; i++){
entrada_dados(time, i);
}
....
My problem is when the team name have some space like to "São Paulo". I have tried some forms to solve, but no one solved my problem.
I tried:
void entrada_dados(Time* time, int i){
fscanf(stdin, "%[^\n] %d %d", time[i].nome, &time[i].gols_marcados, &time[i].gols_sofridos);
};
and:
void entrada_dados(Time* time, int i){
fgets(time[i].nome, 100, stdin);
scanf("%d", &time[i].gols_marcados);
scanf("%d", &time[i].gols_sofridos);
}
but in the first case the output have nothing, and second case the output miss some cases. Someone can help me to understand this problem?
Edit 1:
The definition of .name is:
typedef struct Time{
char nome[100];
int gols_marcados;
int gols_sofridos;
} Time;
Edit 2:
Solution:
One way to solve it:
Try two fscanfs fscanf(stdin, " %[^\n]", time[i].nome);
fscanf(stdin, "%d %d", &time[i].gols_marcados, &time[i].gols_sofridos);
Thank you guys.
Because you have to handle strings with spaces, it's better to use fgets for those.
But mixing fgets and scanf doesn't work too well. We can replace scanf with fgets followed by sscanf.
To decode numbers, we can use strtol or sscanf
We take advantage of the fact that each element/member of Time appears on a separate line in the input file, so we can do fgets for every line. This simplifies the code and makes error checking easier.
Here is the refactored code. It is annotated.
I didn't do this, but, if these sequences are done a lot, we can combine some of these sequences in helper functions to reduce some code replication (e.g. a function that combines the fgets followed by the sscanf)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Time {
char nome[100];
int gols_marcados;
int gols_sofridos;
} Time;
// RETURNS: 1=valid, 0=syntax error
int
entrada_dados(Time *timelist, int i)
{
char buf[100];
char *cp;
Time *tim = &timelist[i];
int valid = 0;
do {
// get name
if (fgets(tim->nome,sizeof(tim->nome),stdin) == NULL)
break;
// strip newline
tim->nome[strcspn(tim->nome,"\n")] = 0;
// get number using strtol
if (fgets(buf,sizeof(buf),stdin) == NULL)
break;
tim->gols_marcados = strtol(buf,&cp,10);
if (*cp != '\n')
break;
// get number using sscanf
if (fgets(buf,sizeof(buf),stdin) == NULL)
break;
if (sscanf(buf,"%d",&tim->gols_sofridos) != 1)
break;
// all input is okay
valid = 1;
} while (0);
return valid;
};
int
main(void)
{
int n = 0;
#if 0
scanf("%d", &n);
#else
char buf[100];
if (fgets(buf,sizeof(buf),stdin) == NULL)
exit(1);
sscanf(buf,"%d",&n);
#endif
// allocate sufficient space
Time *timelist = malloc(sizeof(*timelist) * n);
// read in data
int valid = 0;
for (int i = 0; i < n; i++) {
valid = entrada_dados(timelist, i);
if (! valid)
break;
}
// show the data
if (valid) {
for (int i = 0; i < n; i++) {
Time *tim = &timelist[i];
printf("nome='%s' gols_marcados=%d gols_sofridos=%d\n",
tim->nome,tim->gols_marcados,tim->gols_sofridos);
}
}
return 0;
}
Here is the program input:
3
Campinense
23
12
ABC
30
13
São Paulo
17
82
Here is the program output:
nome='Campinense' gols_marcados=23 gols_sofridos=12
nome='ABC' gols_marcados=30 gols_sofridos=13
nome='São Paulo' gols_marcados=17 gols_sofridos=82

Reading and storing values from csv file in an array using C

#include <stdio.h>
#include <stdlib.h>
int main() {
int c1[100];
char c2[150];
char c3[100];
float c4[100];
float c5[100];
float c6[100];
float c7[100];
char c8[100];
char c9[100];
float c10[100];
char string[10][100];
int i, j;
char c;
FILE *fp1;
fp1 = fopen("sample.csv", "r");
while (1) {
c = fgetc(fp1);
if (c == EOF)
break;
else
printf("%c", c);
}
for (i = 1; i <= 10; i++) {
fscanf(fp1, "%d,%[^,],%[^,],%[^,],%[^,],%d,%d",
&c1[i], &c2[i], &c3[i], &c4[i], &c5[i],
&c6[i], &c7[i], &c8[i], &c9[i], &c10[i]);
}
for (j = 0; j <= 10; j++) {
printf("\n");
printf("%d", c3); //Here i am trying to read the column3 values but getting random integer values.
//This problem continues to every column
}
return 0;
}
I have to read file sample.csv and store values into the array so that I can perform operation on that values.
I am not getting the exact value from the csv file that I have read.
I am getting some random integer value on running the program.
There are many problems in your code:
you do not check if fopen() succeeded.
c must be defined as int for proper end of file testing
you must rewind the file with rewind(fp1); or fseek(fp1, 0L, SEEK_SET); before reparsing the contents with fscanf()
the loop index i must start at 0 instead of 1, because arrays are 0 based.
it is idiomatic in C to use for (i = 0; i < 10; i++) ... to handle 10 lines of input. i <= 10 would iterate 11 times.
you must check the return value of fscanf() to ensure the input stream has the expected format. The format string does not handle empty text fields.
the fscanf() format string is incompatible with the arguments provided
the printf format string "%d\n" in incompatible with the type of the argument: the argument is the array c3 which is passed as a pointer to its first member, not an int as expected.
Simply read a line in a loop until there are no more lines
#include <stdio.h>
#include <string.h>
#define MAX_ITEMS 10000
#define LARGEST_LINE 1000
#define LARGEST_ELEMENT 100
int main(void) {
int c1[MAX_ITEMS];
char c2[MAX_ITEMS][LARGEST_ELEMENT+1]; // large enough for each `c2`
char c3[MAX_ITEMS][LARGEST_ELEMENT+1];
char c4[MAX_ITEMS][LARGEST_ELEMENT+1];
char c5[MAX_ITEMS][LARGEST_ELEMENT+1];
int c6[MAX_ITEMS];
int c7[MAX_ITEMS];
int tmpc1;
char tmpc2[LARGEST_ELEMENT+1];
char tmpc3[LARGEST_ELEMENT+1];
char tmpc4[LARGEST_ELEMENT+1];
char tmpc5[LARGEST_ELEMENT+1];
int tmpc6;
int tmpc7;
int lineno = 0;
char buf[LARGEST_LINE]; // large enough for the largest line
while (fgets(buf, sizeof buf, fp1)) {
++lineno;
// no error, process line
if (sscanf(buf, "%d,"
"%" LARGEST_ELEMENT "[^,],"
"%" LARGEST_ELEMENT "[^,],"
"%" LARGEST_ELEMENT "[^,],"
"%" LARGEST_ELEMENT "[^,],"
"%d,%d",
&tmpd1, tmpc2, tmpc3, tmpc4, tmpc5, &tmpd6, &tmpd7) == 7) {
// line ok, copy tmp variables and update indexes
c1[i] = tmpd1;
strcpy(c2[i], tmpc2);
strcpy(c3[i], tmpc3);
strcpy(c4[i], tmpc4);
strcpy(c5[i], tmpc5);
c6[i] = tmpd6;
c7[i] = tmpd7;
i++;
} else {
// line with error, you may want to report to the user
fprintf(stderr, "line %d with error.\n", lineno);
}
}
// read "error", probably EOF; close file and report
fclose(fp1);
for (int j = 0; j < i; j++) {
printf("item #%d: %d, %s-%s-%s-%s, %d %d\n",
c1[j], c2[j], c3[j], c4[j], c5[j], c6[j], c7[j]);
}
return 0;
}
Also consider putting all those c arrays inside a struct and make 1 single array of that structure.

reading unknown number of of integers and printing them in words

I'm trying to process input from stdin but keep running into walls.
My goal is to read a strem of numbers(0-99) and print each one in words.
My first attempt was:
int main(void) {
char *a[20] = {"zero","one","two","three","four","five","six","seven","eight",
"nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen",
"seventeen","eighteen","nineteen"};
char *b[8] = {"twenty","thirty","fourty","fifty","sixty","seventy","eighty","ninety"};
int num=0, tens=0, ones=0;
while (scanf("%d", &num)==1){
tens = num/10;
ones = num%10;
if (tens>1){
printf("%s ", b[tens-2]);
printf("%s \n", a[ones]);
}
else
printf("%s \n", a[num]);
}
printf("done");
return 0;
}
Output is correct but scanf never terminates the loop.
Second attempt:
int main(void) {
char *a[20] = {"zero","one","two","three","four","five","six","seven","eight",
"nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen",
"seventeen","eighteen","nineteen"};
char *b[8] = {"twenty","thirty","fourty","fifty","sixty","seventy","eighty","ninety"};
char line[1024], *ptr = NULL;
long num;
int tens=0, ones=0;
if(fgets(line, sizeof(line), stdin)!=NULL){
do {
num = strtol(line, &ptr, 10);
tens = num/10;
ones = num%10;
if (tens>1){
printf("%s ", b[tens-2]);
printf("%s \n", a[ones]);
}
else
printf("%s \n", a[num]);
}while (*ptr!= '\n');
}
printf("done");
return 0;
}
Here I get a compilation error and can't find the problem so I don't know if it works.
[UPDATE]: The second code runs but for an input of more then one number like
12 35 51 it prints the first number (twelve) infinitely.
Any help would be greatly appreciated.
You are so close. You just need to validate the return of strtol, and update the pointer address based on the endptr following the call to strtol. You should also check for values outside the range of your conversion as mentioned in the discussion. This is all that is needed:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(void) {
char *a[] = {"zero","one","two","three","four","five","six",
"seven","eight","nine","ten","eleven","twelve",
"thirteen","fourteen","fifteen","sixteen",
"seventeen","eighteen","nineteen"};
char *b[] = {"twenty","thirty","fourty","fifty","sixty",
"seventy","eighty","ninety"};
char line[1024] = "";
long num;
int tens=0, ones=0;
if (fgets (line, sizeof(line), stdin) != NULL) {
char *p = line, *ep = NULL;
errno = 0;
while (errno == 0) {
num = strtol (p, &ep, 10); /* convert to long */
if (p == ep) break; /* no digits, break */
p = ep; /* update p to ep */
if (num < 0 || 99 < num) { /* validate range */
fprintf (stderr, "error: %ld - out of range.\n", num);
continue;
}
tens = num/10;
ones = num%10;
if (tens > 1) {
printf ("%s ", b[tens-2]);
printf ("%s \n", a[ones]);
}
else
printf("%s \n", a[num]);
}
}
printf ("done\n");
return 0;
}
Example Use/Output
$ ./bin/n2string
12 55 61 -1 33 102 4
twelve
fifty five
sixty one
error: -1 - out of range.
thirty three
error: 102 - out of range.
four
done
Look it over and let me know if you have any questions.
The purpose of the code appears to be to print the text version of a digit that was entered. Your code works almost unchanged, I just added a library and ran it.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *a[20] = {"zero","one","two","three","four","five","six","seven","eight",
"nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen",
"seventeen","eighteen","nineteen"};
char *b[8] = {"twenty","thirty","fourty","fifty","sixty","seventy","eighty","ninety"};
char line[1024], *ptr = NULL;
long num;
int tens=0, ones=0;
if(fgets(line, sizeof(line), stdin)!=NULL){
do {
num = strtol(line, &ptr, 10);
tens = num/10;
ones = num%10;
if (tens>1){
printf("%s ", b[tens-2]);
printf("%s \n", a[ones]);
}
else
printf("%s \n", a[num]);
}while (*ptr!= '\n');
}
printf("done");
return 0;
}
Test
19
nineteen
done
Maybe the problem was that you didn't know the purpose of the code.

Jumble solving program crashes on run

I'm working on a program for my Intro to C class that requires me to write a program that solves jumble puzzles (you know, those anagram puzzles you see in the newspaper), based on a dictionary text file that my professor gave us. It alphabetizes words from the dictionary, takes in jumbles from a text file (called "jumble.txt"), alphabetizes those, then runs a string compare to find a match. I've got all the code written, but it immediately crashes when I try to run it, and I can't figure out why. I thought maybe the Stackoverflow users might be able to help me out here.
Here's the code I have:
#include <stdio.h>
#include <strings.h>
#define MAX_WORD_LEN 6
#define MAX_NUM_WORDS 30000
typedef struct {
char word[MAX_WORD_LEN+1];
char sort[MAX_WORD_LEN+1];
} jumble_type;
void bubblesort(char letters[], int length);
int main () {
int words, jumbles;
int j, q;
jumble_type list[MAX_NUM_WORDS];
jumble_type list2[MAX_NUM_WORDS];
// Creating file pointers
FILE *ifp;
FILE *ifp2;
//Opens Jumble and dictionary files and reads the info from them
ifp = fopen("jumbledct.txt", "r");
ifp2 = fopen("jumble.txt", "r");
//Assigns the value of "words" to the first line of jumbledct.txt
fscanf(ifp, "%d", words);
//Assigns the value of "jumbles" to the first line of jumble.txt
fscanf(ifp2, "%d", jumbles);
// Reads the words from the dictionary into the "word" section of our
// list structure.
int i;
for (i = 0; i < words; i++){
fscanf(ifp, "%s", &list[i].word);
strcpy(list[i].sort, list[i].word);
bubblesort(list[i].sort, strlen(list[i].sort));
printf("%s\n", list[i].sort);
}
//Reads from Jumble.txt
for (i = 0; i < jumbles; i++){
fscanf (ifp2, "%s", &list2[i].word);
strcpy(list2[i].sort, list2[i].word);
bubblesort(list2[i].sort, strlen(list2[i].sort));
//printf("%s\n", list2[i].sort);
}
for(j=0;j<jumbles; j++){
printf("JUMBLE PUZZLE # %d: %s\n", j+1, list2[j].word);
int x=0;
for (q = 0; q < words; q++){
if(strcmp(list2[j].sort, list[q].sort)==0){
printf("%s\n", list[q].word);
x++;
}
}
if (x == 0){
printf("Sorry, this puzzle has no solutions. \n\n");
}
printf("\n");
}
return 0;
}
void bubblesort(char letters[], int length) {
char temp;
int x, y;
for(x = 0; x < length; x++){
for (y = x; y < length; y++){
if (letters[x] > letters[y]){
temp = letters[y];
letters[y] = letters[x];
letters[x] = temp;
}
}
}
}
Thanks in advance for all your help.
My C is a little rusty, but shouldn't the third argument to the fscanf function be an address (like &words and &jumbles)?

Resources