if (strcmp(file_name, "stdout") == 0)? - c

I have the following code that creates random numbers and send the output to a filename given by the user.
However I cannot grasp from line 19 on. According to the documentation, when you want to compare two strings to see if they are equal, then you use from the standard library in C the function strcmp, which takes two arguments (string1 and string2), and if they are equal then the result is 0. In the if statemente I have two strings, the first is the file_name given by the user when prompt to do so, and a string "stdout", could anyone tell me how this comparison makes sense?
if (strcmp(file_name, "stdout") == 0)
Additionally, in line 26 you find
if (i % 6 == 1)
which is the modulus (what's remains after performing the division for the numbers in the for loop, and if the remaining is 1 then it makes a fprintf, that I only can understand as printing columns for the rand numbers that will be generated.
Is it correct?
#include <stdio.h> /* include libraries */
#include <string.h>
#include <stdlib.h>
void main() /* declares function main as void */
{
char file_name[100]; /*declares an array of name file_name
with 100 elements */
int i, n; /*declares two integers of name i and n */
FILE *fp; /* declares a variables of type pointer to file */
printf("\nthis program creates random numbers."); /*prints message */
printf("\n\nhow many would you like? "); /*prints question */
scanf("%d", &n); /* gets user input and stores answer in address of
variable n */
printf("in what file would you like them? "); /*prints question*/
scanf("%s", file_name); /*gets user input and store it as string
into the variable array of name file_name */
if (strcmp(file_name, "stdout") == 0) /*if the comparison between
file_name and "stdout" is equal to 0 (both strings are equal)*/
fp = stdout; /* it assigns the pointer to file to standard output*/
else /*if not then */
fp = fopen(file_name, "w");/*opens the file_name in write modus*/
for (i = 1; i <= n; ++i) {/*initializes for loop from one to the value
of n that you entered*/
if (i % 6 == 1) /*if the residuo of i / 6 is 1 for instance 13/6 = 1*/
fprintf(fp, "\n");/* it prints the information from the ?? */
fprintf(fp, "%12d", rand());
}
}

char file_name[100]="smth.txt:;
if (strcmp(file_name, "stdout") == 0){
}//....
if (i % 6 == 0)
fprintf(fp, "\n");
fprintf(fp, "%12d", rand());

Related

How to separate words from numbers in file in c

I need to find the degree of inversion for a set of numbers in a file.
I read input from a .txt file in the form:
SET 1: -3 1 2 0 4
SET 2: 0 1 2 3 4 5
SET 4: 29 39 0 1 3
I do not know how to separate the input (the set and its numbers). I thought of putting them in a struct but so far it's not working.
The degree of inversion = number of numbers that are smaller than their index value. For example, in SET 2, the degree of inversion is 0.
You need to post code on where you are stuck; that is the best way to get help.
Anyway, here is some rough code to help you identify where your issues may be. I have kept it simple to allow you to follow through with how vanilla C does I/O.
#include <stdio.h> /* snprinf, fprintf fgets, fopen, sscanf */
int main(void)
{
char line_buffer[64];
FILE* infile = fopen("yourfile.txt", "r"); /* open file for reading */
while(fgets(line_buffer, 64, infile) != NULL)
{
char set_name[8]; /* construct a string w/ the set number */
snprintf(set_name, 8, "SET %c:", *(line_buffer+4)); /* no. is 5th char */
fprintf(stdout, "%s ", set_name); /* fprintf w/ stdout = printf */
int set[8];
int ind = 0;
for(int i=7; line_buffer[i]!='\0';) /* start from first number and end */
{ /* when string ends, denoted by the '\0' sentinel */
int n; /* using pointer arithmetric, read in and store num & consume */
sscanf(line_buffer+i, "%d %n", set+ind, &n); /* adjacent whitespace */
i += n; /* n from sscanf tells how many chars are read in */
fprintf(stdout, "%d ", set[ind]);
ind +=1;
}
fprintf(stdout, "\n");
}
return 0;
}

Using qsort and strcmp prior to my sctrucs going into txt files

My code pulls data from one text file and then totals the points and enters it into a separate text file, so I would like the program to organize the teams and scores by total points prior to frpintf into the text file. So far the program pulls and runs the data and totals it out and fprintf just fine, should I use qsort to sort and print into the text file, and where in my code do I place it. Here is the text it is reading.
Indians 54 45 5
Twins 45 53 7
Tigers 43 59 8
White_Sox 35 64 9
Royals 30 69 3
Also I know there are no ties in the MLB lol just throwing in an additional variable.
Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
int main(void)
{
struct records {
char filename;
char team[50];
int wins;
int tie;
int loss;
int points;
};
struct records roster;
FILE *ifp = NULL;
FILE *afd = NULL;
const int argv;
char filename2[64] = {0};
char filename[64] = {0};
int points;
int points2;
int total;
printf("\nPlease enter the the .txt file you would like to open: ");
scanf("%63s", filename);
printf("Opened file name %s",filename);
ifp = fopen(filename,"r");
if (ifp == NULL)
{
printf("Could not open");
printf("\nPlease enter the the .txt file you would like to open:");
scanf("%63s", filename);
printf("Opened file name %s",filename);
ifp = fopen(filename,"r");
}
printf("\nReading the file %s \n", filename);
while(fscanf(ifp, "%s %d %d%d" , roster.team, &roster.wins, &roster.loss,
&roster.tie) != EOF)
printf("%s Wins:%d Losses:%d ties:%d\n", roster.team, roster.wins,
roster.loss, roster.tie);
printf("\nWins are worth 2 points ties are worth 1 point and losses are
worth \nzero in overall league standings.");
printf("\nHere are the overall ALCentral Standings!\n");
ifp = fopen(filename, "r");
fopen(filename, "r"); while(fscanf(ifp, "%s %d %d %d", roster.team,
&roster.wins, &roster.loss, &roster.tie) != EOF)
printf("%s Wins:%d Losses:%d ties:%d Total league points:%d\n",
roster.team, roster.wins, roster.loss, roster.tie, (roster.wins * 2 +
roster.tie * 1), total);
printf("closing %s", filename);
fclose(ifp);
printf("\nPlease enter the the .txt file you would like to write to: ");
scanf("%63s", filename2);
printf("Opened file name %s", filename2);
afd = fopen(filename2, "a+");
if (afd == NULL)
{
printf("Could not open"); printf("\nPlease enter the the .txt file you
would like to open: ");
scanf("%63s", filename2);
printf("Opened file name %s", filename2);
afd = fopen(filename2,"a+");
}
ifp = fopen(filename,"r");
fopen(filename, "r");
points = roster.wins * 2;
points2 = roster.tie * 1;
total = points + points2;
while(fscanf(ifp, "%s %d %d %d", roster.team, &roster.wins, &roster.loss,
&roster.tie) != EOF)
fprintf(afd, "%s Wins:%d Losses:%d ties:%d total league points:%d\n",
roster.team, roster.wins, roster.loss, roster.tie, (roster.wins *2 +
roster.tie *1 ), total, filename2);
printf("\nYour stats have been recorded to the selected
file!\nClosing all open files! \nThanks for using the STAT-Master!
Have a great day!
fclose(afd);
fclose(ifp);
return 0;
}
Your logic is quite jumbled. If I understand what you are attempting, you want to read each teams wins, loss and tie record from your data file, and then compute the points that are then used to sort the teams into descending (or perhaps ascending) order and then output the "the overall ALCentral Standings" to either stdout or a file, or both.
Before starting let's talk about your definition of struct records inside of main(). While legal, you generally will want your struct declaration to be at file scope so that the struct type is available to any functions you write to help process the data in your code. Here, you must move the declaration outside of main() because the qsort compare function will need to know what the type struct records is. The compare function cannot be declared and defined in main() because C does not allow nested function declarations. So move your struct outside of main(), e.g.
#define MAXR 16 /* if you need a constant, #define one (or more) */
#define MAXC 64
#define MAXB 1024
typedef struct records {
char team[MAXC];
int wins,
loss,
tie,
points;
} record_t;
(note: using a typedef can make things more convenient)
To begin with, your multiple attempts to read the filename is awkward and never insures you actually have a file open. It just makes a couple of attempts and then effectively gives up validation and just blindly assumes there is a valid file stream to read and write to and presses ahead. This is a recipe for invoking Undefined Behavior.
When ever you do anything in C, and especially when you are dealing with user input or file operations, you must validate every step. You must know whether or not the file is open for reading before you attempt to read. (no matter how many times you attempt to open it) You must validate what you have read before you begin using the values in your code. You must validate the state of your input stream before you attempt your next read, and handle any characters that remain.
With that in mind you can prompt for the filename and attempt to open the filename provided in a continual loop until you validate the file is actually open, e.g.
/** helper function to empty stdin between inputs */
void empty_stdin()
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
...
FILE *fp = NULL; /* file pointer */
do { /* loop until valid filename given and file open */
printf("\nenter input filename: ");
if (scanf (" %63[^\n]", filename) != 1) {
fprintf (stderr, "error: user canceled input.\n");
return 1;
}
empty_stdin(); /* remove '\n' and any add'l chars in input buffer */
fp = fopen (filename, "r"); /* open filename */
if (fp == NULL) /* validate file open for reading */
perror ("fopen-input");
} while (fp == NULL);
printf("Opened file name %s\n\n",filename);
(note: rather than using scanf for user input, fgets provides a better approach to user input and far fewer pitfalls that scanf, example below with roster)
Next, your understanding of how to collect the data in memory in order to sort it, is not evident from your post. When you want to sort a collection of team information, you must read all team information into memory before you can pass the information to qsort for sorting.
You have a struct that holds all of information for each team, you simply need to read each line (record) from your input file into an array or struct which can then easily be passed to qsort for sorting.
To use qsort you first must define a compare function that is used to qsort to order your data. The compare function has a specific declaration:
int compare (const void *a, const void *b);
Where each const void * parameter will be a pointer to one of the elements in your array of records. (in C a void pointer, e.g. void* is a generic pointer that can be assigned from, or to, any other pointer type without a cast -- that is why the compare function's declaration uses that type for the parameters) Your job in writing a compare function is simply to provide a type to the pointers (either by assignment or by explicit cast, your choice) and then a comparison between the values that you wish to sort by. For example, your compare on the points member of each struct could simply be:
/** qsort compare function (descending order of points) */
int compare (const void *a, const void *b)
{
const record_t *ta = a;
const record_t *tb = b;
return (ta->points < tb->points) - (ta->points > tb->points);
}
(where the (a < b) - (a > b) simply evaluates to -1, 0, 1 depending on the inequalites, e.g. if a = 4 and b = 3, you have (0) - (1) which equals -1 meaning a sorts before b)
All that remains is reading each teams data into your array and computing points and then passing your array to qsort.
To read your data into an array, read each line into a buffer, parse the data in the buffer into the individual values, validate that each of the individual values where parsed correctly, compute the points value for each team, increment your array index and then go read the next line. You could do something like the following using fgets to read each line of data:
record_t roster[MAXR] = {{ .team = "" }}; /* array to hold teams */
...
/* read up to MAXR team records from file */
while (ndx < MAXR && fgets (buf, MAXB, fp)) {
/* parse data from buffer filled, saving return */
int rtn = sscanf (buf, " %49s %d %d %d" , roster[ndx].team,
&roster[ndx].wins, &roster[ndx].loss,
&roster[ndx].tie);
if (rtn < 4) /* if less than 4 conversions, get next line */
continue;
/* compute points (2 * wins + ties) */
roster[ndx].points = roster[ndx].wins * 2 + roster[ndx].tie;
ndx++; /* increment index */
}
fclose (fp); /* close file */
(note: you can add a strlen() check of buf to determine if additional characters remain in the line unread -- that is left to you).
With all you data in your array of structs roster, all that remains is passing roster to qsort and then outputting your sorted data.
The following sorts the data and outputs the results to stdout. Writing the output to a file is left to you, but hint, you don't need both ifp and afp and you don't need filename and filename2 or points2, you are only dealing with one file/filename at a time. The sort and output is simple:
/* sort roster based on points (descending order) */
qsort (roster, ndx, sizeof *roster, compare);
/* outpout results */
printf ("Here are the overall ALCentral Standings!\n\n"
"Team Wins Loss Tie Points\n\n");
for (int i = 0; i < ndx; i++)
printf ("%-12s %4d %4d %4d %4d\n", roster[i].team,
roster[i].wins, roster[i].loss, roster[i].tie,
roster[i].points);
Putting it altogether in an example, you could do something like the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXR 16 /* if you need a constant, #define one (or more) */
#define MAXC 64
#define MAXB 1024
typedef struct records {
char team[MAXC];
int wins,
loss,
tie,
points;
} record_t;
/** helper function to empty stdin between inputs */
void empty_stdin()
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
/** qsort compare function (descending order of points) */
int compare (const void *a, const void *b)
{
const record_t *ta = a;
const record_t *tb = b;
return (ta->points < tb->points) - (ta->points > tb->points);
}
int main (void) {
int ndx = 0; /* index for roster array */
char buf[MAXB] = "", /* buffer for fgetrs */
filename[MAXC] = ""; /* filename to read */
record_t roster[MAXR] = {{ .team = "" }}; /* array to hold teams */
FILE *fp = NULL; /* file pointer */
do { /* loop until valid filename given and file open */
printf("\nenter input filename: ");
if (scanf (" %63[^\n]", filename) != 1) {
fprintf (stderr, "error: user canceled input.\n");
return 1;
}
empty_stdin(); /* remove '\n' and any add'l chars in input buffer */
fp = fopen (filename, "r"); /* open filename */
if (fp == NULL) /* validate file open for reading */
perror ("fopen-input");
} while (fp == NULL);
printf("Opened file name %s\n\n",filename);
/* read up to MAXR team records from file */
while (ndx < MAXR && fgets (buf, MAXB, fp)) {
/* parse data from buffer filled, saving return */
int rtn = sscanf (buf, " %49s %d %d %d" , roster[ndx].team,
&roster[ndx].wins, &roster[ndx].loss,
&roster[ndx].tie);
if (rtn < 4) /* if less than 4 conversions, get next line */
continue;
/* compute points (2 * wins + ties) */
roster[ndx].points = roster[ndx].wins * 2 + roster[ndx].tie;
ndx++; /* increment index */
}
fclose (fp); /* close file */
/* sort roster based on points (descending order) */
qsort (roster, ndx, sizeof *roster, compare);
/* outpout results */
printf ("Here are the overall ALCentral Standings!\n\n"
"Team Wins Loss Tie Points\n\n");
for (int i = 0; i < ndx; i++)
printf ("%-12s %4d %4d %4d %4d\n", roster[i].team,
roster[i].wins, roster[i].loss, roster[i].tie,
roster[i].points);
return 0;
}
Example Input File
The file is provided as given, with blank lines in between records.
$ cat dat/teams.txt
Indians 54 45 5
Twins 45 53 7
Tigers 43 59 8
White_Sox 35 64 9
Royals 30 69 3
Example Use/Output
$ ./bin/qsortstrcmp
enter input filename: dat/teams.txt
Opened file name dat/teams.txt
Here are the overall ALCentral Standings!
Team Wins Loss Tie Points
Indians 54 45 5 113
Twins 45 53 7 97
Tigers 43 59 8 94
White_Sox 35 64 9 79
Royals 30 69 3 63
Look things over and let me know if you have further questions.

C Saving Data from a Text File into an Array of Structures

I want to ask about file processing and struct in C language. I am given an assignment where I need to have a .txt file containing: the names of basketball teams, the games they have played in total, the amount of games they have won, etc..
Here is the task:
Get data from user-specified .txt file (eg "data.txt")
Store the data in array of struct
Let the user have the ability to sort by name or the total amount of wins they have.
Here is an example, "data.txt" file:
Structure : name, games played, won at home, lost at home, won away, lost away
Fenerbahce-Dogus 25 12 0 10 3
Tofas 25 11 2 9 3
Anadolu-Efe 26 13 1 6 6
Banvit 26 9 4 8 5
Darussafaka 26 11 2 4 9
So far, I have been trying to allocate a dynamic array (of struct) and save the data from the txt file into said array. However, the program stops responding immediately whenever I try to enter the said "data.txt". as input. Could anybody inform me why this is happening and what should I do to get past this error?
Here is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *name;
int games;
int winsHome, losesHome;
int winsAway, losesAway;
int winsTotal, losesTotal;
int totalPoints;
} scoreboard;
void Load_Scoreboard_Table(char *, scoreboard *);
int main(){
char fileName[40];
FILE *inputFile;
while (1){
printf("Enter the file name> ");
gets(fileName);
inputFile = fopen(fileName,"r");
if (inputFile != NULL){
break;
}
printf("ERROR: The file %s could not be opened.\n",fileName);
printf("Please verify that the file exists.\n");
}
int listLength=0;
char curChar;
while ((curChar=fgetc(inputFile))!=EOF){
if (curChar=='\n'){
listLength++;
}
}
fclose(inputFile);
scoreboard *scoreboard_table = (scoreboard *)malloc(sizeof(scoreboard) * listLength);
Load_Scoreboard_Table(fileName,scoreboard_table);
return 0;
}
void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
FILE *inputFile;
fopen(fileName,"r");
int i=0;
while (fscanf(inputFile, "%s %d %d %d %d %d\n", (scoreboard_table+i)->name,(scoreboard_table+i)->games,(scoreboard_table+i)->winsHome,(scoreboard_table+i)->losesHome,(scoreboard_table+i)->winsAway,(scoreboard_table+i)->losesAway)!=EOF){
(scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
(scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
(scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
i++;
}
}
Update:
I have managed to read from the file and save it in struct array.(Also added a print function). However I still cannot get it to stop freezing once it finishes printing the function (it would freeze after saving data into the array before).
Note: I know many people have warned me not to use gets; but, my teacher told me to use it for now.
Note2: I decided to have a static char name inside the struct
Note3: I have only learned about data structures today, so I'm VERY new to the topic; therefore, please explain things without going into too much detail.
What could be causing the code below to freeze?
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { // defining a struct here
char name[40]; // name of the sports club
//clubs containing multiple words should be written in the following format: 'name-name-name'
//ex : 'Anadolu Efe' should be written as 'Anadolu-Efe' in the text file
//This is to avoid confusion when reading from .txt file
int games;
int winsHome, losesHome;
int winsAway, losesAway;
int winsTotal, losesTotal;
int totalPoints;
} scoreboard;
void Load_Scoreboard_Table(char *, scoreboard *); // reads the .txt file and saves the contents into scoreboard_table
void Display_Scoreboard_Table(scoreboard *, int); // displays scoreboard_table, also takes it's size as input
int main(void){
char fileName[40]; // the name of the file will be stored here (ex: data.txt)
FILE *inputFile; // creating a stream to read from .txt file
while (1){ // Ask user for the name of the file until said file is opened for reading
printf("Enter the file name> ");
gets(fileName); // get string input from user that supports space characters (eg: "data.txt")
inputFile = fopen(fileName,"r"); // try opening file in read mode
if (inputFile != NULL){ //if the file has succesfully opened, then break from the loop
break;
}
printf("ERROR: The file %s could not be opened.\n",fileName); //if the file was not succesfully opened, then print appropriate error message
printf("Please verify that the file exists.\n");
}
int listLength=0; //will be used to dynamically allocate memory for scoreboard_table array (array of structs)
int curChar; // I figured that fgetc returns an integer value
while ((curChar=fgetc(inputFile))!=EOF){ //get a character until EOF
if (curChar=='\n'){ //if it's a newline character then we need to allocate more memory for scoreboard_table array
listLength++;
}
}
fclose(inputFile); // close the file as it's job is done
scoreboard *scoreboard_table = malloc(sizeof(scoreboard) * listLength); // allocating enough memory to store the contents of .txt file
Load_Scoreboard_Table(fileName,scoreboard_table); //save the contents of file on scoreboard_table
while (1){
Display_Scoreboard_Table(scoreboard_table,listLength);
break;
}
free(scoreboard_table); //freeing memory allocated for scoreboard_table
return 0;
}
void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
FILE *inputFile = fopen(fileName,"r"); // creating stream to read from file
if(inputFile == NULL ) { //checking again just in case there is a problem opening the file
printf("ERROR: The file %s could not be opened.\n",fileName);
exit(1);
}
int i=0,j,k;
//the loop below gets data from .txt file line by line until EOF and stores it in scoreboard_table array
while (fscanf(inputFile,"%s %d %d %d %d %d", (scoreboard_table+i)->name,&(scoreboard_table+i)->games,&(scoreboard_table+i)->winsHome,&(scoreboard_table+i)->losesHome,&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway) != EOF){
(scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
(scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
(scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
i++;
}
//the loop below replaces the '-' characters with ' ' in the name of every scoreboard_table array
for (j=0;j<i;j++){
for (k=0;k<40;k++){
if ((scoreboard_table+i)->name[k] == '-'){
(scoreboard_table+i)->name[k] = ' ';
}
}
}
printf("Score records file has been successfully loaded!\n");
}
void Display_Scoreboard_Table(scoreboard *scoreboard_table,int size){
printf("Team G WH LH WA LA Won Lost Points\n");
int i;
for (i=0;i<=size;i++){
printf("%-40s%5d %5d %5d %5d %5d %5d %5d %5d\n",(scoreboard_table+i)->name,(scoreboard_table+i)->games,(scoreboard_table+i)->winsHome,(scoreboard_table+i)->losesHome,(scoreboard_table+i)->winsAway,(scoreboard_table+i)->losesAway,(scoreboard_table+i)->winsTotal,(scoreboard_table+i)->losesTotal,(scoreboard_table+i)->totalPoints);
}
}
Thank you.
Update 2 (With working code):
The issue was caused by me allocating wrong amount of memory for the array of structs called scoreboard_table. To be more specific, I was allocating memory for array that could hold 1 less line than the file.
I have updated the code again. It is working now... (For the most part, except when an unexpected input is entered(such as being fed an empty file, or user entering more characters into gets).)
This code is more than enough for my assignment as my teachers have not asked for a more detailed program(infact, they do get angry if we submit more complicated programs since we have not yet learnt about them in class - which is why I'm using gets() and not fgets() for example).
However I'm curious to hear your opinions on the matter. What do you think I should do to improve this?
By the way, I am aware of the grammar-spelling mistakes in the code. It's just because we need to strictly obey the input-output format in our assignments and typing things differently means losing points.
Code:
/* -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
~ ~ ~ ~ VERY IMPORTANT ~ ~ ~ ~
The text file containing the data should be written in the following format:
"%s %d %d %d %d %d\n" where
%s is the name of the club
If the name of the club contains more than one word, it should be written without any space characters ' '; instead place dash characters '-'
Example: 'Anadolu Efe' should be written as 'Anadolu-Efe' in the text file
complete line example:
"Anadolu-Efe 26 13 1 6 6"
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- */
//including required libraries
#include <stdio.h>
#include <stdlib.h> //used to dynamically allocate memory
#include <string.h> //used for some string manipulation functions
typedef struct { // defining a struct here
char name[40]; // name of the sports club
//clubs containing multiple words should be written in the following format: 'name-name-name'
//ex : 'Anadolu Efe' should be written as 'Anadolu-Efe' in the text file
//This is to avoid confusion when reading from .txt file
int games;
int winsHome, losesHome;
int winsAway, losesAway;
int winsTotal, losesTotal;
int totalPoints;
} scoreboard;
void Load_Scoreboard_Table(char *, scoreboard *); // reads the .txt file and saves the contents into scoreboard_table
void Display_Scoreboard_Table(scoreboard *, int); // displays scoreboard_table, also takes it's size as input
void Search(scoreboard *, int, char *); // searches if a team exists in the scoreboard array and if there is; it prints the stats of the team
void interactive_board(scoreboard *, int, int); // sorts the scoreboard array depending on user input, (sort by: games, points)
/*
This program reads data from a txt data, stores it in an array of structs
The program has the ability to sort the array based on either points or games
It also can search for the name inside said array of structs
*/
int main(){
char fileName[40]; // the name of the file will be stored here (ex: data.txt)
char searchTerm[40]; // search term will be stored here
FILE *inputFile; // creating a stream to read from .txt file
int i; // will be used later in a loop
while (1){ // Ask user for the name of the file until said file is opened for reading
printf("Enter the file name: ");
gets(fileName); // get string input from user that supports space characters (eg: "data.txt")
inputFile = fopen(fileName,"r"); // try opening file in read mode
if (inputFile != NULL){ //if the file has succesfully opened, then break from the loop
break;
}
printf("ERROR: The file %s could not be opened.\n",fileName); //if the file was not succesfully opened, then print appropriate error message
printf("Please verify that the file exists.\n");
}
int listLength=1; //will be used to dynamically allocate memory for scoreboard_table array (array of structs)
int curChar; // I figured that fgetc returns an integer value
while ((curChar=fgetc(inputFile))!=EOF){ //get a character until EOF
if (curChar=='\n'){ //if it's a newline character then we need to allocate more memory for scoreboard_table array
listLength++;
}
}
fclose(inputFile); // close the file as it's job is done
scoreboard *scoreboard_table = malloc(sizeof(scoreboard) * (listLength)); // allocating enough memory to store the contents of .txt file
if (scoreboard_table == NULL){
printf("ERROR: There has been an error allocating memory for scoreboard table array.\n");
exit(1);
}
Load_Scoreboard_Table(fileName,scoreboard_table); //save the contents of file on scoreboard_table
Display_Scoreboard_Table(scoreboard_table,listLength);
while (1){
printf("Enter the name of the team (Exit - X, Sort -S): ");
gets(searchTerm);
i=0;
while (searchTerm[i]!='\0'){
searchTerm[i]=toupper(searchTerm[i]);
i++;
}
if (strcmp(searchTerm,"X")==0){
printf("Bye!\n");
free(scoreboard_table); //freeing memory allocated for scoreboard_table
return 0;
}
else if (strcmp(searchTerm,"S")==0){
printf("Sort by (G: games, P: points): ");
gets(searchTerm);
i=0;
while (searchTerm[i]!='\0'){
searchTerm[i]=toupper(searchTerm[i]);
i++;
}
if (strcmp(searchTerm,"G")==0){
interactive_board(scoreboard_table,listLength,1);
Display_Scoreboard_Table(scoreboard_table,listLength);
}
else if (strcmp(searchTerm,"P")==0){
interactive_board(scoreboard_table,listLength,2);
Display_Scoreboard_Table(scoreboard_table,listLength);
}
else{
printf("ERROR: Invalid input. There is no sort term for '%s'\n",searchTerm);
}
}
else{
Search(scoreboard_table,listLength,searchTerm);
}
}
}
void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
FILE *inputFile = fopen(fileName,"r"); // creating stream to read from file
if(inputFile == NULL ) { //checking again just in case there is a problem opening the file
printf("ERROR: The file %s could not be opened.\n",fileName);
exit(1);
}
int i=0,j,k;
//the loop below gets data from .txt file line by line until EOF and stores it in scoreboard_table array
while (fscanf(inputFile,"%s %d %d %d %d %d", (scoreboard_table+i)->name,&(scoreboard_table+i)->games,&(scoreboard_table+i)->winsHome,&(scoreboard_table+i)->losesHome,&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway) != EOF){
(scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
(scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
(scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
i++;
}
//the loop below replaces the '-' characters with ' ' in the name of every scoreboard_table array
for (j=0;j<i;j++){
for (k=0;k<40;k++){
if (*(((*(scoreboard_table+j)).name)+k) == '-' ){ //if the value of name[k] inside scoreboard_table[j] is equal to '-' character
*(((*(scoreboard_table+j)).name)+k) = ' '; //replace the value of scoreboard_table[j].name[k] to ' ' character
}
}
}
fclose(inputFile); // close the file as it's job is done
printf("Score records file has been successfully loaded!\n"); // notify the user that reading from the file has been successful
}
void Display_Scoreboard_Table(scoreboard *scoreboard_table,int size){
printf("\nTeam G WH LH WA LA Won Lost Points\n\n"); // the variables to be shown in table
int i;
for (i=0;i<size;i++){//for every element in scoreboard_table, print the variables stored
printf("%-40s%5d %5d %5d %5d %5d %5d %5d %5d\n",(scoreboard_table+i)->name,(scoreboard_table+i)->games,(scoreboard_table+i)->winsHome,(scoreboard_table+i)->losesHome,(scoreboard_table+i)->winsAway,(scoreboard_table+i)->losesAway,(scoreboard_table+i)->winsTotal,(scoreboard_table+i)->losesTotal,(scoreboard_table+i)->totalPoints);
}
}
void Search(scoreboard *scoreboard_table, int size, char *searchTerm){ //search for name of team in scoreboard_table
int i,j; //i = index of scoreboard_table array, j = index of name array inside scoreboard_table array
char table_name[40]; // will be used to convert scoreboard_table->name to uppercase and store it
for (i=0;i<size;i++){ // for every element in scoreboard_table
for (j=0;j<40;j++){ // for every character in the name of scoreboard_table[i]->name
table_name[j]=toupper(*(((*(scoreboard_table+i)).name)+j)); //store the upper-case letter of scoreboard_table[i]->name[j] in table_name[j]
}
if (strcmp(table_name,searchTerm)==0){
//if the search term is equal to table_name (which is uppercase version of scoreboard_table[i]->name), then print the statistics and break from the loop.
printf("%s has %d win, %d lost and a total of %d points!\n",(scoreboard_table+i)->name,(scoreboard_table+i)->winsTotal,(scoreboard_table+i)->losesTotal,(scoreboard_table+i)->totalPoints);
break;
}
else if(i==(size-1)){
// if it's the last element of scoreboard_table array and the search term is not equal to scoreboard_table[i]->name
// notify the user that their search term is not found in the scoreboard_table array
printf("That team is unknown! Please try again!\n");
}
}
}
void interactive_board(scoreboard *scoreboard_table, int size, int sort){
//this function sorts the scoreboard_table array using selection sort algorithm
/*
selection sort algorithm sorts an array by repeatedly finding the maximum element from unsorted part and putting it at the beginning.
*/
int i,j,index;
/*
i is used in a for loop to get ith element of scoreboard_table
j is used to determine when the sorting is complete
(ie: if you have a list containing 5 elements, you need to sort the array 4 times at most(in this case, which is selection sort algorithm);
therefore j is used in a for loop : for (j=0;j<(sizeofArray-1);j++)
j is also used to write into jth element of scoreboard_table
*/
int max; //store the max value here
scoreboard temp; //declare a struct named temp, will store temporary data when swapping variables of scoreboard_table array
if (sort==1){ // if sorting based on games
for (j=0;j<size-1;j++){ // explained above, iterate the code below (array) size-1 times
max=(scoreboard_table+size-1)->games; //set max to the last element of the array since this is the unsorted part of array...
index=size-1; //set index to index of last element of the array...
for (i=j;i<size;i++){ //no need to search elements with index less than j since they are already sorted
//therefore start searching elements from j till the last element
if (max<((scoreboard_table+i)->games)){
//if the value of current element > max, then the max value becomes this value and the index of the new max value is stored in index
max=(scoreboard_table+i)->games;
index=i;
}
if (i==(size-1)){ // swap the variables of scoreboard_table[index] with the variables of scoreboard_table[j]
//where j stands for the next unsorted member and index stands for the index of the largest variable
//copy contents of scoreboard_table[j] into temp (BACKUP)
strcpy(temp.name,(scoreboard_table+j)->name);
temp.games=(scoreboard_table+j)->games;
temp.losesAway=(scoreboard_table+j)->losesAway;
temp.losesHome=(scoreboard_table+j)->losesHome;
temp.losesTotal=(scoreboard_table+j)->losesTotal;
temp.totalPoints=(scoreboard_table+j)->totalPoints;
temp.winsAway=(scoreboard_table+j)->winsAway;
temp.winsHome=(scoreboard_table+j)->winsHome;
temp.winsTotal=(scoreboard_table+j)->winsTotal;
//copy contents of scoreboard_table[index] into scoreboard_table[j]
strcpy((scoreboard_table+j)->name,(scoreboard_table+index)->name);
(scoreboard_table+j)->games=(scoreboard_table+index)->games;
(scoreboard_table+j)->losesAway=(scoreboard_table+index)->losesAway;
(scoreboard_table+j)->losesHome=(scoreboard_table+index)->losesHome;
(scoreboard_table+j)->losesTotal=(scoreboard_table+index)->losesTotal;
(scoreboard_table+j)->totalPoints=(scoreboard_table+index)->totalPoints;
(scoreboard_table+j)->winsAway=(scoreboard_table+index)->winsAway;
(scoreboard_table+j)->winsHome=(scoreboard_table+index)->winsHome;
(scoreboard_table+j)->winsTotal=(scoreboard_table+index)->winsTotal;
//copy contents of temp (BACKUP) into scoreboard_table[index]
strcpy((scoreboard_table+index)->name,temp.name);
(scoreboard_table+index)->games=temp.games;
(scoreboard_table+index)->losesAway=temp.losesAway;
(scoreboard_table+index)->losesHome=temp.losesHome;
(scoreboard_table+index)->losesTotal=temp.losesTotal;
(scoreboard_table+index)->totalPoints=temp.totalPoints;
(scoreboard_table+index)->winsAway=temp.winsAway;
(scoreboard_table+index)->winsHome=temp.winsHome;
(scoreboard_table+index)->winsTotal=temp.winsTotal;
}
}
}
}
else{ // if sorting based on points
for (j=0;j<size-1;j++){ // explained above, iterate the code below (array) size-1 times
max=(scoreboard_table+size-1)->totalPoints; //set max to the last element of the array since this is the unsorted part of array...
index=size-1; //set index to index of last element of the array...
for (i=j;i<size;i++){ //no need to search elements with index less than j since they are already sorted
//therefore start searching elements from j till the last element
if (max<((scoreboard_table+i)->totalPoints)){
//if the value of current element > max, then the max value becomes this value and the index of the new max value is stored in index
max=(scoreboard_table+i)->totalPoints;
index=i;
}
if (i==(size-1)){ // swap the variables of scoreboard_table[index] with the variables of scoreboard_table[j]
//where j stands for the next unsorted member and index stands for the index of the largest variable
//copy contents of scoreboard_table[j] into temp (BACKUP)
strcpy(temp.name,(scoreboard_table+j)->name);
temp.games=(scoreboard_table+j)->games;
temp.losesAway=(scoreboard_table+j)->losesAway;
temp.losesHome=(scoreboard_table+j)->losesHome;
temp.losesTotal=(scoreboard_table+j)->losesTotal;
temp.totalPoints=(scoreboard_table+j)->totalPoints;
temp.winsAway=(scoreboard_table+j)->winsAway;
temp.winsHome=(scoreboard_table+j)->winsHome;
temp.winsTotal=(scoreboard_table+j)->winsTotal;
//copy contents of scoreboard_table[index] into scoreboard_table[j]
strcpy((scoreboard_table+j)->name,(scoreboard_table+index)->name);
(scoreboard_table+j)->games=(scoreboard_table+index)->games;
(scoreboard_table+j)->losesAway=(scoreboard_table+index)->losesAway;
(scoreboard_table+j)->losesHome=(scoreboard_table+index)->losesHome;
(scoreboard_table+j)->losesTotal=(scoreboard_table+index)->losesTotal;
(scoreboard_table+j)->totalPoints=(scoreboard_table+index)->totalPoints;
(scoreboard_table+j)->winsAway=(scoreboard_table+index)->winsAway;
(scoreboard_table+j)->winsHome=(scoreboard_table+index)->winsHome;
(scoreboard_table+j)->winsTotal=(scoreboard_table+index)->winsTotal;
//copy contents of temp (BACKUP) into scoreboard_table[index]
strcpy((scoreboard_table+index)->name,temp.name);
(scoreboard_table+index)->games=temp.games;
(scoreboard_table+index)->losesAway=temp.losesAway;
(scoreboard_table+index)->losesHome=temp.losesHome;
(scoreboard_table+index)->losesTotal=temp.losesTotal;
(scoreboard_table+index)->totalPoints=temp.totalPoints;
(scoreboard_table+index)->winsAway=temp.winsAway;
(scoreboard_table+index)->winsHome=temp.winsHome;
(scoreboard_table+index)->winsTotal=temp.winsTotal;
}
}
}
}
}
you have lot of problems in your code like.
Firstly, use fgets() instead of gets(). for e.g
fgets(fileName,sizeof(fileName),stdin);
Secondly, name is pointer member of scoreboard, allocate memory for it first. for e.g
scoreboard_table->name = malloc(SIZE); /* define SIZE */
Thirdly, fgetc() return type is int. check the manual page of fgetc(). So char curChar; should be int curChar;
Finally, in fscanf() while storing integers you need to provide the & address to each argument. for e.g
fscanf(inputFile,"%d",&(scoreboard_table+i)->games)
I try to explain in the comments. Here is the sample code
void Load_Scoreboard_Table(char *, scoreboard *);
int main(void){
char fileName[40], *ret = NULL;
FILE *inputFile;
while (1){
printf("Enter the file name> ");
/* make sure fileName gets correctly stored in buffer as expected */
ret = fgets(fileName,sizeof(fileName),stdin); /* use fgets() instead of gets() */
if(ret == NULL) { /* if failed, check again */
continue;
}
else {
printf("%s",ret); /* if fgets() result is as expected, control comes here */
fileName[strlen(fileName)-1] ='\0';
}
inputFile = fopen(fileName,"r");
if (inputFile != NULL){
break;
}
printf("ERROR: The file %s could not be opened.\n",fileName);
printf("Please verify that the file exists.\n");
}
int listLength=0;
int curChar; /*return type of fgetc() is int */
while ((curChar=fgetc(inputFile))!=EOF){
if (curChar=='\n'){
listLength++;
}
}
fclose(inputFile);
scoreboard *scoreboard_table = malloc(sizeof(scoreboard) * listLength);/* no need to cast the result of malloc() */
scoreboard_table->name = malloc(100);/*name is pointer member, allocate memory for it. must */
Load_Scoreboard_Table(fileName,scoreboard_table);
/* don't forget to free dynamically allocated memory here #TODO */
return 0;
}
void Load_Scoreboard_Table(char *fileName,scoreboard *scoreboard_table){
FILE *inputFile = fopen(fileName,"r");
if(inputFile == NULL ) {
/* some mesage,, error handling #TODO*/
}
int i=0;
while (fscanf(inputFile,"%s %d %d %d %d %d", (scoreboard_table+i)->name,&(scoreboard_table+i)->games,&(scoreboard_table+i)->winsHome,&(scoreboard_table+i)->losesHome,&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway) > 0){
(scoreboard_table+i)->winsTotal = (scoreboard_table+i)->winsHome + (scoreboard_table+i)->winsAway;
(scoreboard_table+i)->losesTotal = (scoreboard_table+i)->losesHome + (scoreboard_table+i)->losesAway;
(scoreboard_table+i)->totalPoints = (((scoreboard_table+i)->winsTotal)*2) + (scoreboard_table+i)->losesTotal;
i++;
}
for(int j =0 ;j<i;j++) {
printf("%d %d %d \n",(scoreboard_table+j)->winsTotal,(scoreboard_table+j)->losesTotal,(scoreboard_table+j)->totalPoints);
}
}
From man 3 gets Why one shouldn't use gets() reason is here.
Never use gets(). Because it is impossible to tell without knowing
the data in advance how many characters gets() will read,
and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has
been used to break computer security. Use fgets() instead.
Pay special attention to contents of your fscanf(). Addresses of int variables have to be passed it's the one of crashing reason of the code.
while (fscanf(inputFile, "%s %d %d %d %d %d\n",
(scoreboard_table+i)->name, &(scoreboard_table+i)->games,
&(scoreboard_table+i)->winsHome, &(scoreboard_table+i)->losesHome,
&(scoreboard_table+i)->winsAway,&(scoreboard_table+i)->losesAway)!=EOF){
Moreover, you should give ear to the other comments like not using gets()
char fileName[40], *p;
fgets(fileName, sizeof fileName, stdin);
if ((p = strchr(fileName, '\n')) != NULL) {
*p = '\0'; /* remove newline */
}
By the way, an allocated memory is needed for char *name in the struct, it's the another reason for crashing, and not forget to free it.

For every possible pair of two unique words in the file, print out the count of occurrences of that pair [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
this code works for single word counts and it differentiate between words with punctuation words with upper lower case. Is there an easy way around to make this code work for pairs as well instead of single words? like I need to print the occurrence of every pair of words in a text file.
Your help is much appreciated,
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE* f = fopen (argv[1], "r");
char buffer[10000];
if (argc != 2)
{
fprintf(stderr, "Usage: %s file\n", argv[0]);
}
fclose(f);
snprintf(buffer, sizeof(buffer), "tr -cs '[:punct:][a-z][A-Z]' '[\\n*]' < %s |"
" sort | uniq -c | sort -n", argv[1]);
return(system(buffer));
}
Example input
The Cat Sat On The Mat
Output
(The Cat, The Sat, The On, The The, The Mat, Cat The, Cat Sat, Cat On, for 30 pairs)
It seems inconceivable that the purpose of your assignment determining the frequency of word-pairs in a file would be to have you wrap a piped-string of shell utilities in a system call. What does that possibly teach you about C? That a system function exists that allows shell access? Well, it does, and you can, lesson done, nothing learned.
It seems far more likely that the intent was for you to understand the use of structures to hold collections of related data in a single object, or at the minimum array or pointer indexing to check for pairs in adjacent words within a file. Of the 2 normal approaches, use of a struct, or index arithmetic, the use of a struct is far more beneficial. Something simple to hold a pair of words and the frequency that pair is seen is all you need. e.g.:
enum { MAXC = 32, MAXP = 100 };
typedef struct {
char w1[MAXC];
char w2[MAXC];
size_t freq;
} wordpair;
(note, the enum simply defines the constants MAXC (32) and MAXP (100) for maximum characters per-word, and maximum pairs to record. You could use two #define statements to the same end)
You can declare an array of the wordpair struct which will hold a pair or words w1 and w2 and how many time that pair is seen in freq. The array of struct can be treated like any other array, sorted, etc..
To analyze the file, you simply need to read the first two words into the first struct, save a pointer to the second word, and then read each remaining word that remains in the file comparing whether the pair formed by the pointer and the new word read already exists (if so simply update the number of times seen), and if it doesn't exist, add a new pair updating the pointer to point to the new word read, and repeat.
Below is a short example that will check the pair occurrence for the words in all filenames given as arguments on the command line (e.g. ./progname file1 file2 ...). If no file is given, the code will read from stdin by default.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXC = 32, MAXP = 100 };
typedef struct {
char w1[MAXC];
char w2[MAXC];
size_t freq;
} wordpair;
size_t get_pair_freq (wordpair *words, FILE *fp);
int compare (const void *a, const void *b);
int main (int argc, char **argv) {
/* initialize variables & open file or stdin for seening */
wordpair words[MAXP] = {{"", "", 0}};
size_t i, idx = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* read from file given, or from stdin (default) */
idx = get_pair_freq (words, stdin);
/* read each remaining file given on command line */
for (i = 2; i < (size_t)argc; i++)
{ if (fp && fp != stdin) { fclose (fp); fp = NULL; }
/* open file for reading */
if (!(fp = fopen (argv[i], "r"))) {
fprintf (stderr, "error: file open failed '%s'.\n",
argv[i]);
continue;
}
/* check 'idx' against MAXP */
if ((idx += get_pair_freq (words, fp)) == MAXP)
break;
}
if (fp && fp != stdin) fclose (fp);
/* sort words alphabetically */
qsort (words, idx, sizeof *words, compare);
/* output the frequency of word pairs */
printf ("\nthe occurrence of words pairs are:\n\n");
for (i = 0; i < idx; i++) {
char pair[MAXC * 2] = "";
sprintf (pair, "%s:%s", words[i].w1, words[i].w2);
printf (" %-32s : %zu\n", pair, words[i].freq);
}
return 0;
}
size_t get_pair_freq (wordpair *pairs, FILE *fp)
{
char w1[MAXC] = "", w2[MAXC] = "";
char *fmt1 = " %32[^ ,.\t\n]%*c";
char *fmt2 = " %32[^ ,.\t\n]%*[^A-Za-z0-9]%32[^ ,.\t\n]%*c";
char *w1p;
int nw = 0;
size_t i, idx = 0;
/* read 1st 2 words into pair, update index 'idx' */
if (idx == 0) {
if ((nw = fscanf (fp, fmt2, w1, w2)) == 2) {
strcpy (pairs[idx].w1, w1);
strcpy (pairs[idx].w2, w2);
pairs[idx].freq++;
w1p = pairs[idx].w2; /* save pointer to w2 for next w1 */
idx++;
}
else {
if (!nw) fprintf (stderr, "error: file read error.\n");
return idx;
}
}
/* read each word in file into w2 */
while (fscanf (fp, fmt1, w2) == 1) {
/* check against all pairs in struct */
for (i = 0; i < idx; i++) {
/* check if pair already exists */
if (strcmp (pairs[i].w1, w1p) == 0 &&
strcmp (pairs[i].w2, w2) == 0) {
pairs[i].freq++; /* update frequency for pair */
goto skipdup; /* skip adding duplicate pair */
}
} /* add new pair, update pairs[*idx].freq */
strcpy (pairs[idx].w1, w1p);
strcpy (pairs[idx].w2, w2);
pairs[idx].freq++;
w1p = pairs[idx].w2;
idx++;
skipdup:
if (idx == MAXP) { /* check 'idx' against MAXP */
fprintf (stderr, "warning: MAXP words exceeded.\n");
break;
}
}
return idx;
}
/* qsort compare funciton */
int compare (const void *a, const void *b)
{
return (strcmp (((wordpair *)a)->w1, ((wordpair *)b)->w1));
}
Use/Output
Given your example of "Hi how are you are you.", it produces the desired results (in sorted order according to your LOCALE).
$ echo "Hi how are you are you." | ./bin/file_word_pairs
the occurrence of words pairs are:
Hi:how : 1
are:you : 2
how:are : 1
you:are : 1
(there is no requirement that you sort the results, but it makes lookup/confirmation a lot easier with longer files)
Removing qsort
$ echo "Hi how are you are you." | ./bin/file_word_pairs
the occurrence of words pairs are:
Hi:how : 1
how:are : 1
are:you : 2
you:are : 1
While you are free to attempt to use your system version, why not take the time to learn how to approach the problem in C. If you want to learn how to do it through a system call, take a Linux course, as doing it in that manner has very little to do with C.
Look it over, lookup the functions that are new to you in the man pages and then ask about anything you don't understand thereafter.

Read a txt file, and memorize into int or long in C

I'm not a C genius. So..first of all sorry for my stupid question.
I have a .txt file or .dta (whatever) and I want to read it in C.
I would like to take the numbers of the txt, formatted as two columns and x rows, and memorize all the data into a matrix (or vector).
Up to know I m using this code:
/*
** File FILE_3.C
**
** Illustrates how to read from a file.
**
** The file is opened for reading. Each line is successively fetched
** using fgets command. The string is then converted to a long integer.
**
** Note that fgets returns NULL when there are no more lines in the file.
**
** In this example file ELAPSED.DTA consists of various elapsed times in
** seconds. This may have been the result of logging the time of events
** using an elapsed time counter which increments each second from the
** time the data logger was placed in service.
**
** Typical data in elapsed.dta might be;
**
** 653 75
** 142 90
** 104 10
** 604 10
** 124 12
**
*/
#include <stdio.h> /* required for file operations */
FILE *fr; /* declare the file pointer */
main()
{
int n;
long elapsed_seconds;
char line[80];
fr = fopen ("elapsed.txt", "rt"); /* open the file for reading */
/* elapsed.dta is the name of the file */
/* "rt" means open the file for reading text */
while(fgets(line, 80, fr) != NULL)
{
sscanf (line, "%ld", &elapsed_seconds);
/* convert the string to a long int */
printf ("%ld\n", elapsed_seconds);
}
fclose(fr); /* close the file prior to exiting the routine */
} /*of main*/
Can you help me?
Thanks for your answer
You can use fscanf rather then fgets and sscanf.
And look at the scanf format carefuly (http://en.wikipedia.org/wiki/Scanf_format_string)
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE * fr;
int row = 0;
int i;
int arr[8][2]; // max 8 rows!
fr = fopen ("file.txt", "r");
if ( fr == NULL )
{
printf( "Can't open file\n" );
exit(0);
}
while( fscanf (fr, "%d %d\n", &arr[row][0], &arr[row][1]) == 2 )
row ++;
for (i = 0; i < row; i++)
printf( "(%d) (%d)\n", arr[i][0], arr[i][1] );
fclose(fr);
}
You have to allocate an array to hold your elapsed_second values.
long * seconds_array;
seconds_array = calloc( SIZEOFARRAY, sizeof(long));
In c an array is more or less the same as a pointer.
Like in this example from http://www.cplusplus.com/reference/cstdlib/calloc/
In the example pData is given a fixed size and this means that you either must know in advance how many numbers you have or you must keep track on how many numbers you've entered and allocate a new pData array when you run out of space.
In the example the numbers are taken from stdin but the principles are the same. when reading from a file. The for loop should probably be more like a while loop in your case.
/* calloc example */
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* calloc, exit, free */
int main ()
{
int i,n;
int * pData;
printf ("Amount of numbers to be entered: ");
scanf ("%d",&i);
pData = (int*) calloc (i,sizeof(int));
if (pData==NULL) exit (1);
for (n=0;n<i;n++)
{
printf ("Enter number #%d: ",n+1);
scanf ("%d",&pData[n]);
}
printf ("You have entered: ");
for (n=0;n<i;n++) printf ("%d ",pData[n]);
free (pData);
return 0;
}
PS dont forget to call free on your array when you are done with it.
http://www.cplusplus.com/reference/cstdlib/free/

Resources