I know this question has been asked a few times, but never in a way that helps me figure out my problem. Essentially, I am reading four text files, all single words separated by a new line, and wanting to store these in a char array. I first count the number of lines in the file and then create a new char array, but for the life of me, I cannot figure out how to get it to read correctly. The last two lines are just to test if it has read the entire file correctly and they always come back a NULL and the question mark symbol.
I want each line to be at the next index in the char array.
Any help would be awesome! Thank you ahead of time.
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
void countAnagrams(char* fileName);
void main ()
{
char *fileNames[] = {"AnagramA.txt","AnagramB.txt","AnagramC.txt","AnagramD.txt"};
countAnagrams(fileNames[0]);
countAnagrams(fileNames[1]);
countAnagrams(fileNames[2]);
countAnagrams(fileNames[3]);
}
void countAnagrams(char* fileName)
{
int anagramCount = 0;
int ch, lines = 0;
//Count number of lines in file
FILE *myfile = fopen(fileName, "r");
do
{
ch = fgetc(myfile);
if(ch == '\n')
lines++;
}while(ch != EOF);
char contents[lines];
int i = 0;
for(i=1;i<lines;i++)
{
fscanf(myfile,"%s",contents[i]);
}
fclose(myfile);
printf("%.12s\n",fileName);
printf("number of lines: %d\n", lines);
printf("first thing: %s\n", contents[0]);
printf("last thing: %s\n", contents[lines-1]);
}
Here's a slight modification of your code that might help you.
The main points:
You can use getline() instead of fscanf(). fscanf() can be used to read line-by-line, but it needs an explicit check for the end of line condition. getline() does this automatically.
As kaylum pointed out, it's necessary to rewind() the file pointer back to the beginning of the file after counting the number of lines.
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
void countAnagrams(char* fileName);
void main ()
{
char *fileNames[] = {"AnagramA.txt","AnagramB.txt","AnagramC.txt","AnagramD.txt"};
countAnagrams(fileNames[0]);
countAnagrams(fileNames[1]);
countAnagrams(fileNames[2]);
countAnagrams(fileNames[3]);
}
void countAnagrams(char* fileName)
{
int anagramCount = 0;
int ch, lines = 0;
//Count number of lines in file
FILE *myfile = fopen(fileName, "r");
do
{
ch = fgetc(myfile);
if (ch == '\n')
lines++;
} while (ch != EOF);
rewind(myfile);
char *contents[lines];
int i = 0;
size_t len = 0;
for(i = 0; i < lines; i++)
{
contents[i] = NULL;
len = 0;
getline(&contents[i], &len, myfile);
}
fclose(myfile);
printf("%.12s\n",fileName);
printf("number of lines: %d\n", lines);
printf("first thing: %s\n", contents[0]);
printf("last thing: %s\n", contents[lines-1]);
}
I think that the problem is char contents[lines] and then fscanf(myfile,"%s",contents[i]) and the printf-s after. contents[i] is char type, and you want to read an array of chars into one char. contents needs to be declared as char* contents[lines] to be able to read a char array into contents[i].
Related
This question already has answers here:
How should character arrays be used as strings?
(4 answers)
Closed 12 months ago.
I have a file with an unknown number of strings and each of these strings is of an unknown length.
I would like to make each line of the file its own string in an array of strings.
I tried to use dynamic allocation in a char** array, but I don't think I'm approaching this correctly.
Below is the code I have tried. It's getting stuck in an infinite loop, and I can't figure out why.
(The text file I'm reading from ends with a line break, by the way.)
#include <getopt.h> //for getopts
#include <sys/stat.h> //to do file stat
#include <dirent.h>
#include <string.h>
#include <pwd.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h> //user macros
#include <stdlib.h>
#include <stdbool.h>
#include <libgen.h>
#include <errno.h>
int main(int argc, char *argv[]) {
//storing the filename inside string
char* filename = argv[1];
FILE *fp1 = fopen(filename, "r");
if (fp1 == NULL) {
fprintf(stderr, "Error: Cannot open '%s'. No such file or directory.\n", filename);
return EXIT_FAILURE;
}
/**
* we begin by getting the number of numbers in the file
* the number of numbers = number of lines = number of line breaks
*/
size_t numNumbers = 0;
// while((fscanf(fp1, "%*[^\n]"), fscanf(fp1, "%*c")) != EOF){
// numNumbers = numNumbers + 1;
// }
char c;
while((c = fgetc(fp1)) != EOF){
if(c == '\n'){
numNumbers++;
}
}
fclose(fp1);
FILE *fp2 = fopen(filename, "r");
char** arrayOfStrings = malloc(numNumbers * sizeof(char*));
for(int i = 0; i < numNumbers; i++) {
int len = 0;
if(((c = fgetc(fp1)) != '\n') && (c != EOF)){
len++;
}
arrayOfStrings[i] = malloc(len * sizeof(char));
}
printf("hello1\n");
//for(int i = 0; i < numNumbers; i++){
// fscanf(fp2, "%s", (arrayOfStrings[i]));
//}
fclose(fp2);
// for(int i = 0; i < numNumbers; i++){
// fprintf(stdout, "%s", arrayOfStrings[i]);
// }
return 0;
}
(I'm very new to C, so please go easy on me!)
In C, strings are terminated with a '0' byte, so it looks like your malloc for each string is 1 character too short -- you've only allowed space for the text.
In addition, you mean the count for the size of each line to be a while loop, not an if statement - right now you are counting each line as length "1".
Finally, you are reading off the end of the file in your commented out fscanf code because you haven't closed and reopened it.
Assuming you want to split the input to the strings by the newline character, would you please try:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *filename; // filename to read
char **arrayOfStrings = NULL; // array of strings
char line[BUFSIZ]; // line buffer while reading
char *p; // temporal pointer to the input line
int i, num; // counter for lines
FILE *fp; // file pointer to read
if (argc != 2) {
fprintf(stderr, "usage: %s file.txt\n", argv[0]);
return EXIT_FAILURE;
}
filename = argv[1];
if (NULL == (fp = fopen(filename, "r"))) {
perror(filename);
return EXIT_FAILURE;
}
// read the input file line by line
while (fgets(line, BUFSIZ, fp)) {
if ((p = strrchr(line, '\n'))) *p = '\0'; // remove trailing newline, if any
if ((p = strrchr(line, '\r'))) *p = '\0'; // remove trailing cr character, if any
if (NULL == (arrayOfStrings = realloc(arrayOfStrings, (num + 1) * sizeof(char **)))) {
// enlarge the array according to the line count
perror("realloc");
return EXIT_FAILURE;
}
if (NULL == (arrayOfStrings[num] = malloc(strlen(line) + 1))) {
// memory for the string of the line
perror("malloc");
return EXIT_FAILURE;
}
strcpy(arrayOfStrings[num], line);
num++;
}
// print the strings in the array
for (i = 0; i < num; i++) {
printf("%d %s\n", i, arrayOfStrings[i]);
}
fclose(fp);
return 0;
}
If the input file looks something like:
This
is
the
input.
Then the output will be:
0 This
1 is
2 the
3 input.
Hi I was trying to create an array of string of an undetermined length in c.
This is my code :
int main()
{
int lineCount=linesCount();
char text[lineCount][10];
printf("%d",lineCount);
FILE * fpointer = fopen("test.txt","r");
fgets(text,10,fpointer);
fclose(fpointer);
printf("%s",text);
return 0;
}
I would like to replace 10 in
char text[lineCount][10];
My code reads out a file I already made the amount of lines dynamic.
Since the line length is unpredictable I would like to replace 10 by a something dynamic.
Thanks in advance.
To do this cleanly, we want a char * array rather than an 2D char array:
char *text[lineCount];
And, we need to use memory from the heap to store the individual lines.
Also, don't "hardwire" so called "magic" numbers like 10. Use an enum or #define (e.g) #define MAXWID 10. Note that with the solution below, we obviate the need for using the magic number at all.
Also, note the use of sizeof(buf) below instead of a magic number.
And, we want [separate] loops when reading and printing.
Anyway, here's the refactored code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
linesCount(void)
{
return 23;
}
int
main(void)
{
int lineCount = linesCount();
char *text[lineCount];
char buf[10000];
printf("%d", lineCount);
// open file and _check_ the return
const char *file = "test.txt";
FILE *fpointer = fopen(file, "r");
if (fpointer == NULL) {
perror(file);
exit(1);
}
int i = 0;
while (fgets(buf, sizeof(buf), fpointer) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
// store line -- we must allocate this
text[i++] = strdup(buf);
}
fclose(fpointer);
for (i = 0; i < lineCount; ++i)
printf("%s\n", text[i]);
return 0;
}
UPDATE:
The above code is derived from your original code. But, it assumes that the linesCount function can predict the number of lines. And, it doesn't check against overflow of the fixed length text array.
Here is a more generalized version that will allow an arbitrary number of lines with varying line lengths:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
int lineCount = 0;
char **text = NULL;
char buf[10000];
// open file and _check_ the return
const char *file = "test.txt";
FILE *fpointer = fopen(file, "r");
if (fpointer == NULL) {
perror(file);
exit(1);
}
int i = 0;
while (fgets(buf, sizeof(buf), fpointer) != NULL) {
// strip newline
buf[strcspn(buf,"\n")] = 0;
++lineCount;
// increase number of lines in array
text = realloc(text,sizeof(*text) * lineCount);
if (text == NULL) {
perror("realloc");
exit(1);
}
// store line -- we must allocate this
text[lineCount - 1] = strdup(buf);
}
fclose(fpointer);
// print the lines
for (i = 0; i < lineCount; ++i)
printf("%s\n", text[i]);
// more processing ...
// free the lines
for (i = 0; i < lineCount; ++i)
free(text[i]);
// free the list of lines
free(text);
return 0;
}
I have the following .csv file containing information about the song, artist, release year (if specified) and number of listens:
Look What The Cat Dragged In,Poison,,Look What The Cat Dragged In by Poison,1,0,1,0
Nothin' But A Good Time,Poison,1988,Nothin' But A Good Time by Poison,1,1,21,21
Something To Believe In,Poison,1990,Something To Believe In by Poison,1,1,1,1
Talk Dirty To Me,Poison,1978,Talk Dirty To Me by Poison,1,1,1,1
A Salty Dog,Procol Harum,1969,A Salty Dog by Procol Harum,1,1,1,1
A Whiter Shade of Pale,Procol Harum,1967,A Whiter Shade of Pale by Procol Harum,1,1,3,3
Blurry,Puddle of Mudd,2001,Blurry by Puddle of Mudd,1,1,1,1
Amie,Pure Prairie League,,Amie by Pure Prairie League,1,0,4,0
Another One Bites the Dust,Queen,1980,Another One Bites the Dust by Queen,1,1,102,102
Bicycle Race,Queen,1978,Bicycle Race by Queen,1,1,3,3
Kiss You All Over,Kiss,1978,Kiss You All Over by Kiss,1,1,5,5
The name of the file and the desired year should be given as command line arguments, and the program should print all songs from that specific year.
e.g.: ./a.out music.csv 1978
Output:
Talk dirty to me
Bicycle Race
Kiss You All Over
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 300
typedef struct {
char song[101], *artist, *line;
long int year;
} music;
int checkYear(char *word)
{
for (int i = 0; i < strlen(word); i++) {
if (!isdigit(word[i]))
return 0;
}
return 1;
}
int main(int argc, char **argv)
{
FILE *fin = fopen(argv[1], "r");
if (!fin)
{
printf("Error opening the file.\n");
return 1;
}
char buf[MAX];
//int nLines = 0; //count the number of lines
//music *array = NULL;
while( fgets(buf, MAX, fin))
{
buf[strcspn(buf, "\n")] = '\0'; // strip the trailing newline
char *word = strtok(buf, ",");
while (word)
{
//printf("Word is : %s\n", word);
if (checkYear(word))
{
//printf("Year : %s\n", word);
music *array = (music *)malloc(sizeof(music));
char *p;
array->year = strtol(word, &p, 10);
if (array->year == atoi(argv[2]))
{
//printf("Year : %ld\t%d\n", array->year, atoi(argv[2]));
if (scanf("%100[^,]", array->song) == 1)
{
printf("Song : %s\n", array->song);
}
}
}
word = strtok(NULL, ",");
}
}
//printf("I've read %d lines\n", nLines);
fclose(fin);
return 0;
}
So far, it's going decent, I can extract the specified year from each line, but now I just need to print the name of the song from those lines (the first token on the line). I thought about using scanf("%[^,]") to read and print everything up until the first comma but it's just stuck in an endless loop. Could you give me an idea? Thanks in advance!
There are multiple problems in the code:
you do not check that enough arguments were passed on the command line, potentially invoking undefined behavior if not.
you do not need to allocate a music structure: you can just parse the first 3 fields, check the year and output the name of the song directly.
strtok() is inappropriate to split fields from a csv file because it treats a sequence of separators as a single separator, which is incorrect and causes invalid parsing if some fields are empty.
sscanf("%[^,]", ...) will fail to convert an empty field.
To split the fields from the csv line, I recommend you use a utility function that behaves like strtok_r() but tailored for csv lines. A simplistic version will stop on , and \n and replace these with a null byte, returning the initial pointer and updating the pointer for the next field. A more advanced version would also handle quotes.
Here is a modified version:
#include <stdio.h>
#include <string.h>
#define MAX 300
char *get_field(char **pp) {
char *p, *start;
for (p = start = *pp; *p; p++) {
if (*p == ',' || *p == '\n') {
*p++ = '\0';
break;
}
}
*pp = p;
return start;
}
int main(int argc, char *argv[]) {
char buf[MAX];
FILE *fin;
char *filename;
char *select_year;
if (argc < 3) {
printf("Missing arguments\n");
return 1;
}
filename = argv[1];
select_year = argv[2];
fin = fopen(filename, "r");
if (!fin) {
printf("Error opening the file %s.\n", filename);
return 1;
}
while (fgets(buf, sizeof buf, fin)) {
char *p = buf;
char *song = get_field(&p);
char *artist = get_field(&p);
char *year = get_field(&p);
if (!strcmp(year, target_year)) {
printf("%s\n", song);
}
}
fclose(fin);
return 0;
}
regarding: scanf("%[^,]") this consumes (upto but not including) the comma.
So the next instruction needs to be something like getchar() to consume the comma. Otherwise, on the next loop nothing will be read because the first character in stdin is that same comma.
I recently write a piece of code that count the number of lines in a text file, however, something the while loop part just don't work properly and loop forever. Anyone can help me to find out what is the problem with that piece of code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fp;
int main() {
fp=fopen("C:\\Users\\Alan\\Desktop\\text.txt","r");
int i=0;
while(!feof(fp)){
i++;
}
fclose(fp);
printf("The Number Of Sentence In That File: %d",i);
getch();
}
The problem is that there is no advance by calling feof(fp), so the execution halts at the beggining of the file. You need to explicitly call something like, getchar(), fscanf(), fgetc(), etc. Here is an example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fp;
int main() {
fp=fopen("test.txt","r");
int i=0, ch=0;
while((ch = fgetc(fp)) > 0){
if(ch == '\n')
i++;
}
fclose(fp);
printf("The Number Of Sentence In That File: %d\n",i);
getchar();
}
For what you want you can try something like this -
char *s;
s=malloc(255);
while(fscanf(fp,"%254s",s)==1)
{
i++;
}
...
free(s);
This will give desired output.
Also -
while(!feof(fp))
feof to control loop is always wrong .And you should never use feof in loop . Refer here
Your loop does not terminate because you are not doing anything with the file within the loop.
Instead of using feof to control the loop, I would propose to use getline().
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fp;
int main() {
fp=fopen("C:\\Users\\Alan\\Desktop\\text.txt","r");
int i = 0;
char *line = NULL;
size_t len = 0;
while (getline(&line, &len, fp) != -1)
i++;
free(line);
fclose(fp);
printf("The Number Of Sentence In That File: %d\n",i);
}
Note: In this case line is set to NULL and len is set 0, hence getline() will allocate a buffer for storing the line. This buffer should be freed before the program returns.
Update
You can use the return value of getline, if you also want to know the number of chars in the file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fp;
int main() {
fp=fopen("C:\\Users\\Alan\\Desktop\\text.txt","r");
int i = 0;
int j = 0;
int read = 0;
char *line = NULL;
size_t len = 0;
while ((read = getline(&line, &len, fp)) != -1) {
i++;
j += read;
}
free(line);
fclose(fp);
printf("The Number Of Lines In That File: %d\n", i);
printf("The Number Of Chars In That File: %d\n", j);
}
I'm currently trying to make a program that will read a file find each unique word and count the number of times that word appears in the file. What I have currently ask the user for a word and searches the file for the number of times that word appears. However I need the program to read the file by itself instead of asking the user for an individual word.
This is what I have currently:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
int num =0;
char word[2000];
char *string;
FILE *in_file = fopen("words.txt", "r");
if (in_file == NULL)
{
printf("Error file missing\n");
exit(-1);
}
scanf("%s",word);
printf("%s\n", word);
while(!feof(in_file))//this loop searches the for the current word
{
fscanf(in_file,"%s",string);
if(!strcmp(string,word))//if match found increment num
num++;
}
printf("we found the word %s in the file %d times\n",word,num );
return 0;
}
I just need some help figuring out how to read the file for unique words (words it hasn't checked for yet) although any other suggestions for my program will be appreciated.
If you want to print every line contained in the file just once, you have to save the strings you have read in a given data structure. For example, a sorted array could do the trick. The code might look as follow:
#include <stddef.h>
size_t numberOfLine = getNumberOfLine (file);
char **previousStrings = allocArray (numberOfLine, maxStringSize);
size_t i;
for (i = 0; i < numberOfLine; i++)
{
char *currentString = readNextLine (file);
if (!containString (previousStrings, currentString))
{
printString (currentString);
insertString (previousStrings, currentString);
}
}
You may use binary search to code the functions containString and insertString in an efficient way. See here for further informations.
You have to split your code into functions (subroutines).
One function would read the file and record all words; the other would count the number of occurrences for each word.
int main(int argc, char const *argv[])
{
char *words[2000];
// Read the file; store all words in the list
int number_of_words = ReadWords("words.txt", words, 2000);
// Now count and print the number of occurrences for each word
for (int i = 0; i < number_of_words; i++)
{
int n = CountOccurrences(words[i], "words.txt");
printf("we found the word %s in the file %d times\n", words[i], n);
}
// Deallocate dynamically allocated memory
Cleanup(words, number_of_words);
}
Note how the main function is relatively short. All the details are in the functions ReadWords and CountOccurrences.
To implement reading all words from a file:
int ReadWords(const char *filename, char *words[], int max_number_of_words)
{
FILE *f = fopen(filename, "rt"); // checking for NULL is boring; i omit it
int i;
char temp[100]; // assuming the words cannot be too long
for (i = 0; i < max_number_of_words; ++i)
{
// Read a word from the file
if (fscanf(f, "%s", temp) != 1)
break;
// note: "!=1" checks for end-of-file; using feof for that is usually a bug
// Allocate memory for the word, because temp is too temporary
words[i] = strdup(temp);
}
fclose(f);
// The result of this function is the number of words in the file
return i;
}
`#include <stdio.h>
#include <stdlib.h>
int main(int argc, char*argv[])
{
int num =0;
char word[2000];
char string[30];
FILE *in_file = fopen(argv[1], "r");
if (in_file == NULL)
{
printf("Error file missing\n");
exit(-1);
}
scanf("%s",word);
printf("%s\n", word);
while(!feof(in_file))//this loop searches the for the current word
{
fscanf(in_file,"%s",string);
if(!strcmp(string,word))//if match found increment num
num++;
}
printf("we found the word %s in the file %d times\n",word,num );
return 0;
}`
if any suggestion plz..most welcome
Blockquote