Initialize text file and store in array - c

Hello I'm creating a function that will read all words in a text file and store each in an array (WordA[]). Here's my code :
#include <stdio.h>
#include <string.h>
#include "dictionary.h"
void
InitializeWords(char *WordA[])
{
char word[31];
int i;
FILE *filep;
filep = fopen("bacon.txt", "r");
if (fp != NULL) { // means that file exists
for (i=0; i<NWORDS; i++){
fscanf(filep, "%s", word);
strcpy(WordA[i], word);
}
fclose(filep);
}
}
The words that will be initialized here in WordA[] will be used in the later part of my program. I've traced where my error is and apparently when I remove the strcpy (WordA[i], word), the words seem to be printing/ read properly.
InitializeWords is called in the main function:
int
main()
{
char *WordA[NWORDS]; // a 1D array of character pointers (addresses)
InitializeWords(WordA);
StartGame(WordA); // starts the program game
return 0;
}
I dont understand what's wrong in copying the word in the array. Please help! Thank you very much!

You need this (attention: this is minimal, non error checking code, there is still room for improvement).
for (i = 0; i<NWORDS; i++) {
fscanf(filep, "%30s", word);
WordA[i] = malloc(strlen(word) + 1); // <<<< added this line
strcpy(WordA[i], word);
}
WordA is an array of uninitialized pointers. So you need to allocate memory for each of the words using malloc(strlen(word) + 1);. The +1 if because of the NUL string terminator.
At the end of the program you should free the allocated memory like this:
void FreeWords(char *WordA[])
{
int i;
for (i = 0; i<NWORDS; i++) {
free(WordA[i]);
}
}
...
FreeWord(WordA);

Related

C read file content into an array of strings

I need to load the contents of a file into two string arrays. I tried the following and it is not working.
file.txt contains 10 records and each record has two string values separated by whitespace.
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char line[12][20];
FILE *fptr = NULL;
int i = 0;
int tot = 0;
fptr = fopen("file.txt", "r");
char arr[20][20];
while (fgets(line, sizeof(line), fptr)) {
strcpy(arr[i],line);
i++;
}
tot=i;
for (int i=0; i<tot; i++) {
printf("first value %s",arr[i][0]);
printf("second value is %s",arr[i][1]);
printf("\n");
}
return 0;
}
If I understand correctly, you're trying to store data in a structure like:
{{"line1A", "line1B"}, {"line2A", "line2B"}, {"line3A", "line3B"}}
It looks like you need an array where each element consists of two arrays (strings), one for the first value and one for the second value on each line. If this is the case, you need a three dimensional array of chars.
In the example below I've declared arrayOfLines as array with 12 elements each of which has 2 arrays of chars (for your two values per line), with space for 20 chars in each string (NULL terminated char array)
There are some other problems with your code:
The first parameter for fgets() should be a char * - a pointer to a string buffer. Your code passes in a multi-dimensional array of chars.
Your while loop should continue until fgets returns NULL
You need to split each line into multiple strings
Check for buffer overruns when copying strings with strcpy()
In the example code I used strtok() delimited by a " " space character - you may need to play around with this - strtok can accept an array of chars to be used as a delimiter. In the example, I split the first string using the first space char, and the second string is delimited by the end of line.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
// Array for 12 lines, each with 2 strings, each string max 20 chars
// Adjust values as required.
char arrayOfLines[12][2][20];
FILE *fptr = NULL;
int i = 0;
int tot = 0;
fptr = fopen("file.txt", "r");
// char arr[20][20]; not needed
char line[20];
while(fgets(line, sizeof(line) / sizeof(line[0]), fptr) != NULL)
{
// Rudimentary error checking - if the string has no newline
// there wasn't enough space in line
if (strchr(line, '\n') == NULL) {
printf("Line too long...");
return EXIT_FAILURE;
}
// Split string into tokens
// NB: Check for buffer overruns when copying strings
char *ptr1 = strtok(line, " ");
strcpy(arrayOfLines[i][0], ptr1);
char *ptr2 = strtok(NULL, "\n");
strcpy(arrayOfLines[i][1], ptr2);
i++;
}
tot=i; // Unecessary - just use a different variable in your loop and use i as the upper bound
for (int i=0;i<tot;i++)
{
printf("first value %s\n", arrayOfLines[i][0]);
printf("second value is %s\n", arrayOfLines[i][1]);
printf("\n");
}
return 0;
}
printf("first value %s",arr[i][0]);
printf("second value is %s",arr[i][1]);
Basicly all you are doing is printing 2 chars from i word when you want to print full string you should do it like this: printf("%s",arr[i]); You said that value is separated by whitespace so when you are getting line from file you will save it to arr[i] (if first line in file contains "Hello World", your arr[0] will contain "Hello World") when you want to split it into 2 printf you need to print them char by char until space.
Edit: I reminded myself about function sscanf you can use it to get data from file array like you whould do it with keyboard input
You can use this to do that
Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void){
char line[12][20];
char arr[20][20];
FILE *fptr=NULL;
int i=0;
fptr = fopen("file.txt", "r");
if(!fptr){
printf("cant open file\n");
exit(1);
}
while(fgets(*line, sizeof(line), fptr)){
strncpy(arr[i],*line, sizeof(*line));
i++;
}
for (int j=0;j<i;j++){
printf("%s\n", arr[j]);
}
return 0;
}
Notes and changes I made on your code:
Check fptr as return value of open() if it's NULL decide what to do.
Remove unnecessary tot variable and use another index j in last for loop.
Use strncpy() as a better version of strcpy()
Correct way of print arr, printf("%s\n", arr[j]);
\n can be embed on first printf()

Strange behaviour of printf with array when passing pointer to another function

To study for the exam we are trying to do some exercise from past exams.
In this exercise we get a header file and we have to create a function that read an input file and print onto the stdout only the parts of strings that do not contain digits.
(We have to pass the pointer of the string red to the main function).
We tried to do it with a an array but when printing the first word is empty or has strange characters. Instead doing a malloc allocation works fine.
What is also strange is that printing before everything an empty string will fix the code.
Therefore we don't understand why using an array of char the first word is not printed correctly, although it is saved in the buffer.
Including a printf before the while loop in the main function will reset the problem.
Using dynamic allocation (malloc) and not static allocation (array) will fix the print.
Iterating over the whole array and set all the memory to 0 does not fix the problem.
Therefore the pointer is correct as with printing an empty string it prints it correctly, but I really cannot understand what cause the issue.
Question are:
How it is possible that printing an empty string the print is correct?
Array is allocated on the stack therefore it is deallocated when the program exit the scope, why is only the first broken and not all the words?
#include "word_reader.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
const char * read_next_word(FILE * f) {
char buffer[WORD_MAX_LEN];
char * word = buffer;
for (int i = 0; i < WORD_MAX_LEN; ++i)
buffer[i] = 0;
//char * buffer = malloc(sizeof(char) * WORD_MAX_LEN);
int found = 0;
int c = 0;
int i = 0;
while (!found && c != EOF) {
while ((c = fgetc(f)) != EOF && isalpha(c)) {
found = 1;
buffer[i] = c;
++i;
}
buffer[i] = '\0';
}
if (found) {
return word;
//return buffer; // when use malloc
}
return 0;
}
int main(int argc, char * argv[]) {
FILE * f = fopen(argv[1], "r");
if(!f) {
perror(argv[1]);
return EXIT_FAILURE;
}
const char * word = 0;
//printf(""); // adding this line fix the problem
while ((word = read_next_word(f))) {
printf("%s\n", word);
}
fclose(f);
return 0;
}
the header file contain only the read_next_word declaration and define WORD_MAX_LEN to 1024. (Also include
the file to read (a simple .txt file)
ciao234 44242 toro
12Tiz23 where333
WEvo23
expected result:
ciao
toro
Tiz
where
WEvo
actual result
�rǫs+)co�0�*�E�L�mзx�<�/��d�c�q
toro
Tiz
where
WEvo
the first line is always some ascii characters or an empty line.

Convert ASCII code to string in C

I am trying to create a char array based on a single ASCII code. The folowing code does not compile correctly, even though "num" is cast to a char:
//Returns the ASCII counterpart of a number, such as 41 = A, 42 = B, 43 = C, etc.
char numToASCII(int num) {
char[] string = {(char)num, "\0"};
return string;
}
For the task that I am given, it is very important that "string" be a character array/string and not a single char. Any help would be appreciated.
The array must be initialized to constant expressions and your function should return a pointer if you want to return an array.
If you just want to return a char, then use the following code instead:
char numToASCII(int num) {
return (char)num;
}
If you want to return a string which contains the character, then you should use the following code:
#include <stdlib.h>
char *numToASCII(int num) {
/*
* Use malloc to allocate an array in the heap, instead of using a
* local array. The memory space of local array will be freed after
* the invocation of numToASCII.
*/
char *string = malloc(2);
if (!string)
return 0;
string[0] = num;
string[1] = 0;
return string;
}
Use the free() function to free the space allocated by malloc().
Try this..
You want to find the character for the ASCII code,then try this code:
#include<stdio.h>
int main()
{
int num;
printf("\nEnter ASCII Code Number:\t");
scanf("%d", &num);
printf("\nASCII Value of %d: \t%c", num, num);
printf("\n");
return 0;
}
In this code it will get the ASCII code from the user and it will print the character for the ASCII code as default.
Not sure if this helps but pulling text from a file comes back as ascii, I needed a string and got around it by checking the string length, sorry for extra steps as I too am very new.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *fp;
char firstbuff[yourchoice];
char secondbuff[yourchoice];
char sentence[yourchoice];
int stringlenght;
fp = fopen("test.txt", "r");
//Here add a means of counting the lines in the file as linecount
for(int j = 0; j < linecount; j++)
{
fgets(firstbuff; 1000; fp);
//get string length and use for loop to individually ascii copy as characters into array
stringlength = strlen(firstbuff);
for(int i = 0; i < stringlength; i++)
{
secondbuff[i] = (char)firstbuff[i];
}
//string concat
strcat(sentence, secondbuff);
}
printf("%s\n", sentence);
fclose(fp);
}

fscanf usage in c - Values not saving properly

I have a small sample program to illustrate my issue below: I have a simple text file with three words (each in a new line) which fscanf reads, assigns to a temporary variable and then transfers to a string array. Yet, the values do not seem to transfer to the array. Also, when I remove the comment // from the second printf in the while loop I get a seg fault.
I'm fairly new to C, so only now learning the usage of these functions! Thanks in advance for assistance!
#include <stdio.h>
#include <string.h>
int main (int argc, char* argv[])
{
char* words[15];
char tmp[45];
int i = 0;
FILE* fp = fopen("small", "r");
while (fscanf(fp, "%s", tmp) == 1)
{
printf("%s\n", tmp);
words[i] = tmp;
i++;
//printf("%s ", words[i]);
}
printf("\n");
printf("Words 0 = %s\n", words[0]);
printf("Words 2 = %s\n", words[1]);
printf("Words 3 = %s\n", words[2]);
fclose(fp);
}
Output
pears
apples
zipper
Words 0 = zipper
Words 2 = zipper
Words 3 = zipper
In your code, words[i] = tmp; is not the way to store each input to the words array. That only stores the base address of the tmp array into each words[i] and later, while printing, it actually prints the latest content of the tmp on every iteration.
If you want to get the contents of the tmp array into each words[i], you need to either
Allocate memory to each words[i] and use strcpy()
Use strdup() and assign that to words[i].
In either of cases, you have to free() the allocated memories before exit.
I had the same problem in the past.
The problem is that when you read from the file, the word is kept in the buffer, and then you store it to the variable temp.
The thing is that when you read the next word, the contents of the buffer change. And this affects the previous call too!
So you read "pears", you print "pears" and words[0] = "pears"
Then you read "apples", you print apples and words[1] = "apples". BUT ALSO words[0] = "apples" now!!
And so on...
What you need to do is before reading the file, to allocate memory with malloc for every words[i] and get it equal to "".
e.g. words[0] = "" etc.
Then when you start reading the file, you should use the strcpy() function for temp and words[i]. This will solve your problem.
I tried to answer this as simply as i could because in the past that issue troubled me and confused me a lot.
The first important problem with your code is this line
char* words[15];
It gives you an array of 15 char pointers (char*). That is not the same as an array of 15 strings. There are no memory for storing the strings.
To get memory for storing the strings, you can do:
char words[15][45];
// ^ ^^
// no * memory for each of the 15 strings
Now you have memory for 15 strings. Each string can be up to 44 chars.
With this change you don't need the tmpvariable - just read directly into words. Something like:
#include <stdio.h>
#include <string.h>
int main (int argc, char* argv[])
{
char words[15][45];
int i = 0;
FILE* fp = fopen("small", "r");
if (!fp)
{
printf("no such file\n");
return 0;
}
while ((i < 15) && (fscanf(fp, "%44s", words[i]) == 1))
{ // ^^^^^^^^ is the same as &words[i][0]
i++;
}
printf("\n");
int t;
for (t = 0; t < i; ++t)
{
printf("Words %d = %s\n", t, words[t]);
}
fclose(fp);
return 0;
}
Some other important changes added:
1) After fopen you must check for NULL
2) For scanf with %s always give a max size (i.e. %44s) so there can't be buffer overflow
3) Make sure to stop the while when you have read 15 strings (to prevent buffer overflow)
4) Only print as many strings as you have read in
Finally I added return 0 to the end of main

How to add string to array of strings in C

So I am getting re-acquainted with C, and this one concept has me particularly stuck.
The goal is to create a dynamically allocated array of strings. I have this done, first creating a null array and allocating the appropriate amount of space for each string entered. The only problem is, when I try to actually add a string, I get a seg fault! I can't figure out why, I have a hunch that it is from improper allocation as I can't see anything wrong with my strcpy function.
I have looked exhaustively on this site for an answer, and I have found help, but can't quite close the deal. Any help you can provide would be greatly appreciated!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int count = 0; //array index counter
char *word; //current word
char **array = NULL;
char *term = "q"; //termination character
char *prnt = "print";
while (strcmp(term, word) != 0)
{
printf("Enter a string. Enter q to end. Enter print to print array\n");
// fgets(word, sizeof(word), stdin); adds a newline character to the word. wont work in this case
scanf("%s", word);
//printf("word: %s\nterm: %s\n",word, term);
if (strcmp(term, word) == 0)
{
printf("Terminate\n");
}
else if (strcmp(prnt, word) == 0)
{
printf("Enumerate\n");
int i;
for (i=0; i<count; i++)
{
printf("Slot %d: %s\n",i, array[i]);
}
}
else
{
printf("String added to array\n");
count++;
array = (char**)realloc(array, (count+1)*sizeof(*array));
array[count-1] = (char*)malloc(sizeof(word));
strcpy(array[count-1], word);
}
}
return ;
}
word has no memory allocated to it. Your program in its current form is trampling over unallocated memory as users enter words into your program.
You should guesstimate how large your input would be and allocate the input buffer like this:
char word[80]; // for 80 char max input per entry

Resources