read text file and show text line in random - c

I want a code to read a text file that is include some question and then select one of the questions in random and show for user till all of the question shows;
For example question:
How old are you?
Where are you from?
Now, this is my code but i don't Know to continue.
int main()
{
int i = 0, line = 5;
char ch[1000];
char *str;
time_t t;
srand((unsigned) time(&t));
FILE *myfile;
myfile = fopen("question.txt","r");
if (myfile== NULL)
{
printf("can not open file \n");
return 1;
}
while (fgets(ch,1000, myfile)!=NULL)
printf("%s",ch);
fclose(myfile);
line = 5;
int counter;
for( i = 0 ; i < line ; i++ ) {
counter = rand() % 6;
printf("first question: %s\n", ch[counter]);
}
return 0;
}
How can i to continue?

I'd read the enitire file into a contiguous block of memory, then count the number of lines in the file (in memory) , then make an array of pointers - one pointer to each line and change all the '\n's to `'\0``s .
Finally I'd pick pointers from the array in a random order (using a basic shuffle algorithm) and display the question pointed to to the user.
if the list of questions is too big to fit in memory, the user will probably fall asleep before answering them all so, I'm assuming that won't happen.

Related

fscanf consumes first letter in file. How do I fix it?

I am making a program for a class that reads the contents of a .csv file. I am using a while loop inside of a for loop to scan the contents into two separate arrays, and when it prints the contents, everything is right, except it is missing the first letter in the file. We are not allowed to use any functions from the library except what is permitted.
Code in question:
void readFile(FILE *fptr, int size)
{
int i, a;
a = size / 2;
printf("number of lines in readFile is %d:\n", size);
double y[50];
char x[50];
for (i = 0; i < a; i++)
{
while (fscanf(fptr,"%c,%lf,", &x[i], &y[i]) ==2);
}
printf("%c, %.2lf: ", x[0], y[0]);
//a loop to make sure it scanned properly by displaying array contents
for (i = 0; i < a; i++)
{
printf("%c, %.2lf:\n", x[i], y[i]);
}
}
I tried with no luck to !feof(fptr), != EOF, but these are not supposed to be used in the intro class I am taking. I am out of ideas to fix it.
This is the output of the program above:
number of lines in readFile is 4:
, 20.00:
, 20.00:
E, 30.00:
number of lines is 4:
A few issues ...
The fscanf format is wrong. It needs a leading space to skip over newlines.
Unless you intend to operate on the data read in readFile (vs. passing it back to caller), having function scoped x and y arrays will go out of scope when the function returns.
The caller of readFile should pass the maximum array count but let the function determine the actual number of entries.
Whenever I see two or more "parallel" arrays [indexed by the same variable], I would use a struct. Particularly for .csv data.
.csv files are of the form: a,b\nc,d\n and not a,b,\nc,d,\n so the trailing , in the fscanf is incorrect.
Using nested loops for the data input doesn't work.
No need for feof. Just loop until the fscanf return is not 2.
Here is the corrected code. It is annotated:
#include <stdio.h>
#include <stdlib.h>
// data for single .csv line
struct data {
char x;
double y;
};
// readFile -- read in .csv file
// RETURNS: count of records/lines read
size_t
readFile(FILE *fptr, struct data *arr, size_t size)
// fptr -- open file stream
// arr -- pointer to data array
// size -- maximum number of elements in arr
{
int count = 0;
while (1) {
// check for overflow of array
if (count >= size) {
fprintf(stderr,"readFile: too much data for array\n");
exit(1);
}
// point to current struct/record
struct data *cur = &arr[count];
// read in the .csv line -- stop on error or EOF
if (fscanf(fptr, " %c,%lf", &cur->x, &cur->y) != 2)
break;
// advance the count of the number of valid elements
++count;
}
return count;
}
int
main(int argc,char **argv)
{
struct data arr[50];
// skip over program name
--argc;
++argv;
if (argc != 1) {
printf("wrong number of arguments\n");
exit(1);
}
// open the input file
FILE *fptr = fopen(argv[0],"r");
if (fptr == NULL) {
perror(argv[0]);
exit(1);
}
// read in the data lines
size_t count = readFile(fptr,arr,sizeof(arr) / sizeof(arr[0]));
fclose(fptr);
// print the array
for (size_t idx = 0; idx < count; ++idx) {
struct data *cur = &arr[idx];
printf("%c, %.2f:\n",cur->x,cur->y);
}
return 0;
}
Here is the sample input I used to test the program:
J,23
D,37.62
F,17.83
Here is the program output:
J, 23.00:
D, 37.62:
F, 17.83:

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.

How to improve my code to fill an array from a text table?

I'm a research assistant at a mental health clinic, and I'm trying to write a C program which will convert raw scores (on four subtests) into T scores. C, for better or for worse, is the language I'm most familiar with, but it's been a while since I've written anything, so please excuse my ignorance.
Each raw score on each subtest only corresponds to one T score. However, the converse doesn't hold: Each T score can correspond to multiple raw scores (especially at either extreme of the scale), and some T scores don't correspond to any raw scores.
My solution to the problem of representing this data in a text file is to represent the data in eight columns, every odd column (indices [0], [2], [4], and [6]) representing the T score and every even column representing the raw score that corresponds to it, which seems to solve this for now. If a T score doesn't have a corresponding raw score, I've inserted -1 to keep fscanf happy.
However, I was hoping that maybe you can help me work out a more intelligent solution. I'm also wondering if there's a better data structure that will allow me to intelligently represent and manipulate the asymmetric relationship between T scores and raw scores, maybe so that there would be one entry for each T score and a range of possible values for the subtests that could yield that T score? The file looks like this:
20,0,20,0,20,-1,20,0
20,1,20,1,21,-1,20,1
20,2,20,2,22,0,20,2
20,3,20,3,23,1,20,3
20,4,20,4,24,2,20,4
20,5,20,5,25,3,20,5
20,6,20,6,26,4,20,6
20,7,20,7,27,5,20,7
20,8,20,8,28,6,20,8
20,9,20,9,29,7,20,9
You can see what I have so far below. It does the following:
Using a for loop and a two-dimensional integer array, it retrieves the data from the file and enters it into the array.
The table has 83 rows, so I capped the loop at 83 iterations, but I'm sure there must be a better way to do this so I won't have to hard-code it into the program (I was thinking maybe a while loop that stops when a certain number, like -2, is detected?).
The -1 trick seems to work for now, but I'm also hoping there's a better way to process the table input so that I can use it as is. But I don't really understand the syntax for fscanf well enough to implement something better. Could you give me any pointers on that?
Using further for loops, it runs through the raw score rows and checks for identity between the score the user has entered and its place in the table. I was wondering if there's a clever way to nest these operations into a superordinate for loop?
When the numbers match up, a T score is assigned and the results are printed.
Here's the code:
#include <stdio.h>
int main(int argc, char *argv[]) {
int tab[8][83];
int r_v, r_s, r_bd, r_mr;
int t_v, t_s, t_bd, t_mr;
int i;
FILE *input;
input = fopen(argv[1], "r");
printf("Subtest A score?\n");
scanf("%i", &r_v);
printf("Subtest B score?\n");
scanf("%i", &r_s);
printf("Subtest C score?\n");
scanf("%i", &r_bd);
printf("Subtest D score?\n");
scanf("%i", &r_mr);
for (i = 0; i < 83; i++) {
fscanf(input, "%i,%i,%i,%i,%i,%i,%i,%i", &tab[0][i], &tab[1][i], &tab[2][i], &tab[3][i], &tab[4][i], &tab[5][i], &tab[6][i], &tab[7][i]);
}
for (i = 0; i < 83; i++) {
if (r_v == tab[1][i]) {
t_v = tab[0][i];
}
}
for (i = 0; i < 83; i++) {
if (r_s == tab[3][i]) {
t_s = tab[2][i];
}
}
for (i = 0; i < 83; i++) {
if (r_bd == tab[5][i]) {
t_bd = tab[4][i];
}
}
for (i = 0; i < 83; i++) {
if (r_mr == tab[7][i]) {
t_mr = tab[6][i];
}
}
printf("The participant had the following raw scores: %d, %d, %d, and %d.\n", r_v, r_s, r_bd, r_mr);
printf("Which corresponds to the following T scores: %d, %d, %d, and %d.\n", t_v, t_s, t_bd, t_mr);
return 0;
}
Error Handling
To start, the posted code lacks error-checking. The user may fail to provide a file name, or may provide a non-existent file name. The file may fail to open. The user may enter non-numeric input. The input values may not be found in the table.
Failure to provide a file name can be caught by checking argc at the beginning of the program. Failure to open the file can be handled by checking the value returned from fopen() and exiting with a message when a null pointer is returned.
If an input value is not found in the table, no value is stored in the associated variable. One way of handling this problem is to initialize the associated variable to a sentinel value which is not expected in the table. I have chosen -1 in the code below.
To handle user input, a get_integer() function could be added which takes an input prompt message as an argument and returns the input number. If the user enters malformed input, the function continues to prompt for the input until correct input is given. This function can also validate that input is a non-negative integer, to guard against assigning a value based on a user input value of -1.
One refinement might be to place an upper limit on how many times a user may provide bad input before exiting the program with a message.
Data Structure
Instead of storing the table as a 2d array and accessing the individual fields of the table through indices, I would suggest creating a structure for the lines of the table, and a table[] array of these structs. This would allow for descriptive field names and make the code much more clear.
Reading the File
I would suggest using fgets() to fetch lines from the file. This function returns a null pointer when end-of-file has been reached, allowing control with a while loop. The sscanf() function can be used to parse each line and to store values in the appropriate locations. As with all functions which return meaningful values, the value returned from sscanf() should be checked to be sure that input is as expected. If not, the situation can be handled, perhaps by exiting the program with an error message. I would also consider constructing the table from the file before asking for more user input.
As each line is successfully added to the table, a line counter can be incremented to keep track of the number of rows in the table[] array.
Searching the Table
Only one loop is needed here. The line counter can be used to establish the upper bound on the number of rows to be checked. As OP has suggested that each search value is unique, once it has been found and stored the associated variable will not be changed again. If a search value is not found in the table, the associated variable continues to hold the initial value (-1).
A refinement would be to add a flag to indicate when all search values have been found, and to break out of the loop early when this occurs.
Here is an example program:
#include <stdio.h>
#include <stdlib.h>
#define MAX_ROWS 100
#define BUF_SZ 1024
struct Record
{
int t_v;
int r_v;
int t_s;
int r_s;
int t_bd;
int r_bd;
int t_mr;
int r_mr;
};
int get_integer(const char *prompt);
int main(int argc, char *argv[])
{
struct Record table[MAX_ROWS];
int r_v, r_s, r_bd, r_mr;
int t_v = -1;
int t_s = -1;
int t_bd = -1;
int t_mr = -1;
FILE *input;
if (argc < 2) {
fprintf(stderr, "Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
input = fopen(argv[1], "r");
if (input == NULL) {
fprintf(stderr, "Unable to open file: %s\n", argv[1]);
exit(EXIT_FAILURE);
}
/* Read table into array */
int line = 0;
char buffer[BUF_SZ];
while (fgets(buffer, sizeof buffer, input) != NULL) {
if (sscanf(buffer, "%i,%i,%i,%i,%i,%i,%i,%i",
&table[line].t_v,
&table[line].r_v,
&table[line].t_s,
&table[line].r_s,
&table[line].t_bd,
&table[line].r_bd,
&table[line].t_mr,
&table[line].r_mr)
!= 8) {
fprintf(stderr, "Format error in line %d\n", line);
exit(EXIT_FAILURE);
}
++line;
}
fclose(input);
r_v = get_integer("Subtest A score?\n");
r_s = get_integer("Subtest B score?\n");
r_bd = get_integer("Subtest C score?\n");
r_mr = get_integer("Subtest D score?\n");
for (int i = 0; i < line; i++) {
if (r_v == table[i].r_v) {
t_v = table[i].t_v;
}
if (r_s == table[i].r_s) {
t_s = table[i].t_s;
}
if (r_bd == table[i].r_bd) {
t_bd = table[i].t_bd;
}
if (r_mr == table[i].r_mr) {
t_mr = table[i].t_mr;
}
}
printf("The participant had the following raw scores: "
"%d, %d, %d, and %d.\n",
r_v, r_s, r_bd, r_mr);
printf("Which corresponds to the following T scores: "
"%d, %d, %d, and %d.\n",
t_v, t_s, t_bd, t_mr);
return 0;
}
int get_integer(const char *prompt)
{
char buf[BUF_SZ];
int ret;
do {
printf("%s", prompt);
fflush(stdout);
if (fgets(buf, sizeof buf, stdin) == NULL) {
fprintf(stderr, "Input error in get_integer()\n");
exit(EXIT_FAILURE);
}
} while (sscanf(buf, "%i", &ret) != 1 || ret < 0);
return ret;
}
And here is an example interaction using the posted input file:
λ> ./tvals t_vals.dat
Subtest A score?
3
Subtest B score?
4
Subtest C score?
5
Subtest D score?
6
The participant had the following raw scores: 3, 4, 5, and 6.
Which corresponds to the following T scores: 20, 20, 27, and 20.
Uhmm.. i didn't get that code very well.
As i can see, if A score is 5, t_v is 20 (either if a score was 0).
I don't see you loaded the values in the file to the tab matrix.
So tab is unitialized too.
Anothed thing if you want to improve your code.
You made 5 loops.. when you can simply merge all these into one.
Aforloop with at the top there's fscanf and after it all your conditions.
#include <stdio.h>
#include <stdlib.h>
#define NO_OF_ROW 100 //You can change if no of rows increases
#define EACH_LINE_SIZE 100
#define SUBTEST_A 1
#define SUBTEST_B 3
#define SUBTEST_C 5
#define SUBTEST_D 7
int main(int argc, char *argv[])
{
int tab[8][NO_OF_ROW] = {{0}};
int r_v, r_s, r_bd, r_mr;
int t_v=0, t_s=0, t_bd=0, t_mr=0;
int i;
FILE *input;
int no_rows =0;
char* line = malloc(EACH_LINE_SIZE);
input = fopen("User.txt", "r");
if(NULL == input)
{
return 0;
}
printf("Subtest A score?\n");
scanf("%i", &r_v);
printf("Subtest B score?\n");
scanf("%i", &r_s);
printf("Subtest C score?\n");
scanf("%i", &r_bd);
printf("Subtest D score?\n");
scanf("%i", &r_mr);
while (fgets(line, EACH_LINE_SIZE, input) != NULL)
{
sscanf(line, "%d,%d,%d,%d,%d,%d,%d,%d", &tab[0][i], &tab[1][i], &tab[2][i], &tab[3][i], &tab[4][i], &tab[5][i], &tab[6][i], &tab[7][i]);
//printf("%d,%d,%d,%d,%d,%d,%d,%d\n", tab[0][i], tab[1][i], tab[2][i], tab[3][i], tab[4][i], tab[5][i], tab[6][i], tab[7][i]);
i++;
if(NO_OF_ROW <= i)
{
printf("Stop file reading \n");
break; //if the file has more line -Just end it here
}
}
no_rows = i;
for(i=0 ; i < no_rows ; i++)
{
if (r_v == tab[SUBTEST_A][i])
{
t_v = tab[SUBTEST_A-1][i];
}
if (r_s == tab[SUBTEST_B][i])
{
t_s = tab[SUBTEST_B-1][i];
}
if (r_bd == tab[SUBTEST_C][i])
{
t_bd = tab[SUBTEST_C-1][i];
}
if (r_mr == tab[SUBTEST_D][i])
{
t_mr = tab[SUBTEST_D-1][i];
}
}
printf("The participant had the following raw scores: %d, %d, %d, and %d.\n", r_v, r_s, r_bd, r_mr);
printf("Which corresponds to the following T scores: %d, %d, %d, and %d.\n", t_v, t_s, t_bd, t_mr);
free(line);
return 0;
}
Instead of constant 83, tried with different method, so you can vary the number of lines
Also instead of 4 loops, tried to fit in single for loop

How to edit specific parts of a file based on user input in C?

I am doing a homework assignment that requires me to create a program for making a dictionary. Most of my assignment is done, but I am stuck on the most complicated part. The part of the assignment I'm stuck on reads:
Editing a Dictionary (E)
Insert a new word (I) (15 points)
If the word is available, it should alert a message.
Otherwise, insert the new word
Delete a word (D) (15 points)
If the word is not available, it should alert a message.
Otherwise, delete the word
Editing a word (U) (10 points)
If the word is not available, it should alert a message
Currently the file I am working with looks like this:
Name of product: Dictionary
Description: Spanish to English Dictionary
Developer: Robert
Date of Creation: 12/02/2017
Number of words: 0
***************************************************************************
1. Red Rojo
2. Cat Gato
3. Apple Manzana
4. Love Amor
5. Car Carro
and I am wondering how I can read, and do the operations above. Most of the stuff on google is very complicated for my current skillset. Here is what I have so far? Can someone ELI5 the general process of what I should be doing in this case? Should I be using structs? How can I interact with the file in the way my professor wants me to? Here is my basic code I have for this section so far:
int editDictionary(char *oDict) {
char array[1000];
char temp[100];
FILE * dictPtr; // dictPtr = dictionary.dic file pointer
/* fix directory for dictionaries */
strcat(temp,"./dicts/");
strcat(temp,oDict);
strcpy(oDict,temp);
/* open dictPtr file for rw */
dictPtr = fopen (oDict,"a+");
fscanf(dictPtr,"%s",array[1]);
/* text scan values */
for(int i = 0; i <5; i ++) printf("%s", array[i]);
return 1;
}
Your task is pretty tedious and requires knowledge of some inbuilt functions in C.
Since, this is your homework assignment, providing the entire code to you would do no good in improving your current skillset. So, I will provide the code for performing the delete operation the dictionary which is the trickiest of all. Rest you have to figure out yourself. The code in delete_dict is more than enough to help you write other functions.
I've added the explanations in the code for most of the functions used but you should still look up their documentation to understand what each function does.
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const char *WORD_COUNT_LABEL = "Number of words: ";
void delete_word(const char *filename, const char *word)
{
//add alerts
char read[100];
FILE *f = fopen(filename, "r");
int exists = 0; //the count of words that exist
//check if word exists
//fgets is used to read a line into the buffer/temp memory read
while (fgets(read, 100, f))
{
//strstr - finds substring
if (strstr(read, word))
{
exists++;
}
}
if (exists == 0)
{
fclose(f);
return;
}
//The main objective to read the file two times is
//because we want to edit the NUMBER_OF_WORDS in the file as well
//now we know that a word exists
//so move flie pointer to beginning
fseek(f, 0, SEEK_SET);
FILE *nf = fopen("dict_t.txt", "w");
int count;
char num[10];
char *p;
while (fgets(read, 100, f))
{
//if word count label is found update it
//return the pointer to the location of match
if (p = strstr(read, WORD_COUNT_LABEL))
{
p += strlen(WORD_COUNT_LABEL);
//incrementing the pointer to the position where number is to be updated
count = atoi(p); //converts integer from char * to int
count -= exists;
sprintf(num, "%d", count); //converts interger from int to char *
strcpy(p, num); //copy new number at that location
strcat(p, "\n");
}
else if (p = strstr(read, word))
{
//if we find the word to be deleted
//we set the first character in read as NULL
//so that nothing is written onto the new file.
read[0] = '\0';
}
//writes char * to file
fputs(read, nf);
}
//rest is self explanatory
fclose(nf);
fclose(f);
remove(filename);
rename("dict_t.txt", filename);
}

Write system call C , fills file with garbage

I am facing some issues when trying to filter specific words from a file, and write them into a new file.
What I am trying to do is writing only words that comes after '&' until the first digit.
For example (This is the content of the file I am reading from):
& some 12 test1 test2
$ thisword 4 no no no no
For the above input , I want to write into a new file the words some and thisword only.
My code is working but , instead of printing only those words , it is printing garbage as well.
int main (argc,argv)
int argc;
char *argv[];
{
int inpfd,outpfd,n;
int i=0;
char tmp[2],buff[BUFFSIZE]; //This is our buffer
//Open the output file of ispell
inpfd = open("outputfile.txt",O_RDONLY);
//Check if open command failed
if(inpfd == -1) {
printf("Failed to open file");
exit(1);
}
//Here we are reading from output file
read(inpfd,buff,999);
buff[999] = '\0';
close(inpfd);
outpfd = open("w.txt",O_WRONLY);
if(outpfd == -1) {
printf("Cannot open file for writing!");
exit(1);
}
//Looping over the Buffer
for (i=0; i <BUFFSIZE; i++) {
printf("This is the char : %c \n",buff[i]);
if(buff[i] == '&') {
i++;
while( !(isdigit(buff[i])) ) { //Write into output file
//As long as we didnt reach
tmp[0] = buff[i]; // To the digit
write(outpfd,tmp,1);
i++;
}
write(outpfd,"\n",1); //Moving to the next line
}
}
close(outpfd);
return 0;
}
This the output of the file after the writing (I am pasting only small part of the garbage):
some
thisword
^#^#^#<FD>^?^#^#<80><B2>-<AD><FD>^?^#^#<B0>
<B0>be^#^#^#^#೵[^X^?^#^#^#<B4>-<AD><FD>^?^#^#s^X<F0>[^X^?^#^#^#<FF>^#^#^#^#^#^#
^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#/
I have no idea what is this garbage , can someone please assist?
Your problem is in this code
read(inpfd,buff,999);
buff[999] = '\0';
close(inpfd);
where you are ignoring the actual length of what you are reading
You should at least use the length of data actually read -- like this
int len = read(inpfd,buff,999);
buff[len] = '\0';
close(inpfd);
However note that the above have it own issues, as read does not always return everything in one go and can terminate early for interrupts etc etc, but that is beyond the scope of this question. For very simple apps, you may just get away with the simple modification.
Now after null terminating knowing the actual length of the file from the result of read, you also need to fix your loop -- the first step would be to have your outer loop only looking at the data that you read, so
So instead
for (i=0; i <BUFFSIZE; i++) {
use the actual length;
for (i=0; i <len; i++) {
Your code inside the loop contains several issues as well, loop termination for one, that you will have to fix as well.
You are looping over the entire size of your buffer, or 999 items.
for (i=0; i <BUFFSIZE; i++) {
The input file is almost certainly shorter than 999 items. So once you're done processing the supplied input, you're just processing garbage until your counter reaches 999!

Resources