Reputation:
I am currently collecting input from a file but my program separates each letter into the char array instead of each word. How can I change my code to get each word?
char c, fileName[20];
FILE *f;
void getFile() {
f = fopen(fileName, "r");
while((c = fgetc(f)) != EOF) {
printf("%c",c);
}
fclose(f);
}
Upvotes: 1
Views: 3160
Reputation: 8286
You can use a scanset with fscanf or sscanf. This scanset, %29[a-zA-Z]
, reads lower and upper case English characters and stops when it encounters a character not in the set. The 29 limits the maximum number of characters to read so as to not overwrite the buffer, word[30]
. When fscanf fails, the else will read one character from the file and give fscanf another try at reading another word.
This also uses the command line to pass in the file to read as argv[1].
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[])
{
char word[30] = {'\0'};
int ch = 0;
FILE *pf = NULL;
if ( argc != 2) {//command requires program name and a file name
printf ( "useage: program filename\n");
return 1;
}
if ( ( pf = fopen ( argv[1], "r")) == NULL) {
perror ( "could not open file");
return 1;
}
while ( 1) {
if ( ( fscanf ( pf, "%29[a-zA-Z]", word)) == 1) {
printf ( "%s\n", word);
}
else {
if ( ( ch = fgetc ( pf)) == EOF) {//read one character and check for end of file
break;
}
//could do something here with the value of ch if needed
}
}
printf ( "--DONE--\n");
return 0;
}
This will allocate an array for each word. As words are added the array is expanded using realloc.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, char *argv[])
{
char **words = NULL;//pointer for words
char **temp = NULL;
char word[30] = {'\0'};
int ch = 0;
int each = 0;
int found = 0;
int count = 0;
int wordsize = 0;
FILE *pf = NULL;
if ( argc != 2) {//command requires program name and a file name
printf ( "useage: program filename\n");
return 1;
}
if ( ( pf = fopen ( argv[1], "r")) == NULL) {
perror ( "could not open file");
return 1;
}
while ( 1) {
if ( ( fscanf ( pf, "%29[a-zA-Z]", word)) == 1) {
found = 0;
for ( each = 0; each < wordsize; each++) {
if ( strcmp ( words[each], word) == 0) {
found = 1;
break;
}
}
if ( found == 0) {
wordsize += 1;// increment number of words
temp = realloc ( words, wordsize * sizeof ( char *));//reallocate for another word
if ( temp != NULL) {
words = temp;
words[wordsize - 1] = malloc ( strlen ( word) + 1);//malloc for the word itself
if ( words[wordsize - 1] != NULL) {
strcpy ( words[wordsize - 1], word);
}
else {
printf ( "malloc failed\n");
wordsize -= 1;
break;
}
}
else {
printf ( "realloc failed\n");
wordsize -= 1;
break;
}
}
printf ( "%s\n", word);
}
else {
if ( ( ch = fgetc ( pf)) == EOF) {//read one character and check for end of file
break;
}
//something could be done with ch if needed
}
}
printf ( "--DONE Reading file--\n");
for ( each = 0; each < wordsize; each++) {// print each word
printf ( "%s\n", words[each]);
}
count = 0;
printf ( "Enter a word to search for\n");
if ( ( scanf ( "%29[a-zA-Z]", word)) == 1) {
for ( each = 0; each < wordsize; each++) {
if ( strcmp ( words[each], word) == 0) {
printf ( "Found %s at index %d\n" word, each);
count++;
}
}
printf ( "Found %s %d times\n" word, count);
}
for ( each = 0; each < wordsize; each++) {//release memory
free ( words[each]);
}
free ( words);
return 0;
}
Upvotes: 1
Reputation: 53016
fgetc()
returns an int
you cannot store EOF
in a char
variable.fopen()
didn't return NULL
.You can use this technique to read words like this
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAX_BUFFER_SIZE 256
char **load_words_from_file(const char *filename)
{
size_t wordcount;
size_t charcount;
char buffer[MAX_BUFFER_SIZE];
int chr;
FILE *file;
char **words;
void *pointer;
file = fopen(filename, "r");
if (file == NULL)
return NULL;
wordcount = 0;
charcount = 0;
words = NULL;
while ((chr = fgetc(file)) != EOF)
{
/* it's a white space or it exceeded buffer size, it's a word delimiter */
if ((isspace(chr) != 0) || (charcount >= sizeof(buffer) - 1))
{
/* 'nul' terminate 'buffer' for strcpy() and strlen() */
buffer[charcount] = '\0';
pointer = realloc(words, (1 + wordcount) * sizeof(char *));
if (pointer == NULL) /* failure, free allocated memory and return NULL */
goto failure;
words = pointer;
words[wordcount] = malloc(1 + charcount);
charcount = 0; /* reset character count */
if (words[wordcount] == NULL)
goto failure;
strcpy(words[wordcount], buffer);
wordcount += 1;
}
else
{
/* store the character and count it */
buffer[charcount] = (char)chr;
charcount += 1;
}
}
pointer = realloc(words, (1 + wordcount) * sizeof(char *));
if (pointer == NULL)
goto failure;
words = pointer;
words[wordcount] = NULL; /* this will let you know when to stop fetching words */
fclose(file);
return words;
failure:
for (size_t i = 0 ; i < wordcount ; ++i)
free(words[i]);
free(words);
return NULL;
}
int
main()
{
const char *filename = "your-file-name-here";
char **words = load_words_from_file(filename);
size_t counter = 0;
if (words == NULL)
{
printf("no words found in the file\n");
return -1;
}
while (words[counter] != NULL)
{
printf("%zuth word: %s\n", 1 + counter, words[counter]);
free(words[counter]); /* this program will not use it again */
counter += 1;
}
free(words);
return 0;
}
the strtok()
method would also work, but it's harder to understand.
Note the use of goto
, it's a benign usage, although some people think that goto
is always harmful, that's not true, using it like this makes the program adhere to the DRY priniciple.
Upvotes: 0
Reputation: 100
You could use char * fgets ( char * str, int num, FILE * stream );
Then use char *strtok(char *str, const char *delim)
for example
#include <stdio.h>
int main()
{
FILE * pFile;
char mystring [100];
const char delimters[2] = " ,:";
char *token;
pFile = fopen ("myfile.txt" , "r");
if (pFile == NULL) perror ("Error opening file");
else {
if ( fgets (mystring , 100 , pFile) != NULL )
/* get the first token */
token = strtok(mystring, delimiters);
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );
token = strtok(NULL, delimiters);
}
fclose (pFile);
}
return 0;
}
Upvotes: 1
Reputation: 11728
Use fscanf(3)
instead
char word[256], *p;
while(fscanf(f, "%s", &word) != EOF) {
printf("%s\n", word);
/* break down word into individual chars */
for(p=word; *p; p++) {
printf("%c ", *p);
}
printf("\n");
}
Upvotes: 0