Copy string to element of struct array - c

I'm attempting to copy a C-string, which is read in from a file to an element of a struct array, but it is not copying. When I attempt to print, the word is not there. I'm kind of new to C. Below is my code. Many thanks for your help.
typedef struct Tree{
int numTimes; //number of occurrences
char* word; //the word buffer
}Node;
#include "proj2.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[]){
FILE* readIn; //read file pointer
FILE* writeOut; //write file pointer
char buffer[18]; //allocate buffer ***please do not fuzz
int length = 0;
int count = 0;
Node* array = (Node*) malloc(sizeof(Node));
/*if(argc < 3){ //if the number of command line arguments is < 3, return EXIT_FAILURE
return EXIT_FAILURE;
}*/
argv[1] = "/Users/magnificentbastard/Documents/workspaceCPP/proj2/Password.txt"; //****testing
argv[2] = "outFile.txt"; //****testing
readIn = fopen(argv[1], "r"); //opens the selected argument file for reading
writeOut = fopen(argv[2], "w"); //opens the selected argument file for writing
if(readIn == NULL){ //if there
printf("ERROR: fopen fail.\n");
return EXIT_FAILURE; //exits if the file opens
}
while(fscanf(readIn, "%18s", buffer) == 1){ //loop to read in the words to the buffer
count++; //counts the words coming in
modWord(buffer); //modifies the words coming in
array = (Node*)realloc(array, sizeof(Node));
for(int i = 0; i < count; i++){ //****not copying over...HELP
strcpy(array[i].word, buffer);
}
}
//Node array[count];
fprintf(stderr, "%d ", count); //***for testing purposes only
int elements = sizeof(array)/sizeof(array[0]); //***testing assigns num elements
fprintf(stderr, "%d ", elements); //***testing prints num elements
fclose(readIn); //closes the in-file
fclose(writeOut); //closes the out-file
return EXIT_SUCCESS;
}

array[count] doesn't allocate the memory. I believe what you're trying to implement here is single-linked list of strings.
What you're trying to do can be achieved, but you'd need to allocate memory for array by using malloc/free combo. What's more, what you're trying to achieve should by done by either making Node.word an array of fixed size OR a pointer and allocating the memory on Node-by-Node basis.
Length of an array cannot be retrieved by use of sizeof operator as sizeof is evaluated in compile and it'll always return a size of a pointer on your platform.

Related

Using malloc, and transferring what's in the allocated memory to a file

so I'm testing out a program that I made and for some reason some things are not working.
Please note that the code that I typed in the first and second problem are not related.
So although the names for some things are the same, they are not in the same .c file, neither do they #include each other
First is this: I FIXED IT!
Second problem is this: I have a for loop that is based on two factors. The first factor affects the value based on the character (reading argv[2]), the second factor affects the value based on how many copies of it self it has. I'm trying to get the data in that for loop into memory, and then from memory to a file.
For some reason, nothing is being transferred into the file.
It looks something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[])
{
FILE *filename;
float length, rate, bytesper;
char *data;
data = malloc(sizeof(strlen(argv[2]) * length * rate * bytesper);
if(data == NULL)
{
printf("\nMemory could not be allocated.");
return -1;
}
filename = fopen(argv[1], "wb");
if(filename == NULL)
{
printf("File %s was not created", argv[1]);
return -1;
}
for(size_t i = 0; argv[3][i] != '\0'; i++)//reads each character until NULL
{
for(size_t j = 0;
{
int a[i][j];
a[i][j] = value(argv[3][i], j);
//value is the function I made that takes the character and the j value into account
*ptr = a[i][j] + '0';//did + '0' to make sure the int is converted into char
}
}
if( (fwrite(ptr, sizeof(char), rate*strlen(argv[3])*length, filename)) != rate*strlen(argv[3])*length)
{
printf("\nWas not able to copy data to file.");
}
fclose(filename);
free(ptr);
return 0;
}

Why is it not printing the array?

I want to take the contents from a file and print them out in a random order. Right now I am just trying to take the contents from the file and printing it back out. for example right now the file has:
0 Abdelmeged Zane
1 Attri Sonal
And it prints out the second line not the first.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]){
FILE *file;
char string[50];
char array[100];
int i = 0;
char *p;
file = fopen(argv[1], "r");
if(file == NULL) {
perror("Error opening file");
return(-1);
}
printf("\nOriginal Array: \n");
while(fgets(string, 100, file)!= NULL) {
printf(string);
p = &array[i];
strcpy(p, string);
i++;
}
i = 0;
printf("\nShuffled Array: \n");
while(i < 20){
printf("%c", array[i]);
i++;
}
fclose(file);
return(0);
}
The problem with your code is you declare char array[100]; and then essentially overwrite the string you store in it with strcpy(p, string); with each iteration of your while loop. There is no need to use a pointer p in this case. What you need to do is allocate multiple pointers to hold multiple strings. The normal way is to allocate some number of pointers (10 below -- see MAXLINES), and then allocate space for each string as you use each pointer. The following is a quick example (note there are many different ways to do this). Also, since you are allocating memory, you are responsible for freeing it as well (also shown below). Drop a comment if you have questions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLINES 10
int main(int argc, char* argv[]){
FILE *file;
char string[50];
char **array = NULL;
int i = 0;
if (argc < 2) {
fprintf (stderr, "Error: insufficient input. Usage: %s <filename>\n", argv[0]);
return 1;
}
file = fopen(argv[1], "r");
if(file == NULL) {
perror("Error opening file");
return 1;
}
array = calloc (MAXLINES, sizeof (*array)); /* MAXLINES char pointers */
if (!array) {
fprintf (stderr, "Error: calloc pointer allocation failed\n");
return 1;
}
printf("\nOriginal Array: \n");
while(fgets(string, 100, file)!= NULL) {
printf(" %s", string);
array[i] = strdup (string); /* strdup allocates space for string */
i++;
}
fclose(file); /* close it here, you are done with it */
i = 0; /* print array stored in memory */
printf("\nShuffled Array: \n");
while (array[i])
{
printf(" %s", array[i]);
i++;
}
i = 0;
while (array[i]) /* free memory dynamically allocated: */
{
free (array[i]); /* free array/string memory */
i++;
}
if (array) free (array); /* free pointer allocation */
return 0;
}
Note: you should also save the number of strings read after your loop with fgets (e.g. int numlines = i;). Do this before you reset i = 0;. That way you have a convenient reference to the number of strings to use in your shuffle. (you can also always use the while (array[i]) loop to count them again, but why?
input file:
$ cat dat/abde.txt
0 Abdelmeged Zane
1 Attri Sonal
output:
$ ./bin/shufs dat/abde.txt
Original Array:
0 Abdelmeged Zane
1 Attri Sonal
Shuffled Array:
0 Abdelmeged Zane
1 Attri Sonal
You are copying the string you read into the second char array, offsetting the start point by one each time. So at the end, assuming you don't have a buffer overflow, then your array will hold the first character of each line up to the last, which it will hold in its entirety.
Depending where you are in your study, either create a static array of arrays of chars to hold each line, or an array of pointers and malloc the copy you save.

How to include the spaces?

I am trying to write a program that takes the words from a file, and puts those in a dynamic array. However when I try to run my code the program copies it all except for the spaces. How do I fix this?
This is a test does it work?
But I get the following:
Thisisatestdoesitwork?
char** getWords(char* filename, int* pn){
char** tmp = (char**)malloc( 1000*sizeof(char));
int *temp=(int*)malloc(1000*sizeof(int);
int c;
int counter = 0;
FILE* fileInput = fopen(filename, "r");
if(fileInput == NULL){
return tmp; // return if file open fails
}
while((c=fgetc(fileInput)) != EOF){
result = fscanf(fileInput, "%c", &c); //try to read a character
if(isalpha(c)){ //chararect alphabetical
tmp[counter] = c; // safe int to array
counter ++;
printf("%c", c); fflush(stdout);
}
else{ // if read not succesfull
fscanf(fileInput, ""); // needs to scan anything not a character
}
if(counter > 100){ // to not exceed the array
break;
}
if(feof(fileInput)){ // to check if at the end of the file
break;
}
}
fclose(fileInput); // closing file
*pn = counter;
return tmp;}
My main Function:
int main(int argc, char* argv[]){
int n;
char** a = getWords("opdracht_4_5.c", &n);
if (a != NULL){
puts("gevonden woorden:");
for (int i = 0;i < n; i++){
printf("%3d %s\n",i,a[i]);
}
for (int i = 0;i < n; i++){
free(a);
}
free(a);
}
return (EXIT_SUCCESS);
}
There are quite a few problems with your code. Here's a start:
You don't test the return value of fopen().
You don't test the return value of malloc().
You assign the return value of fgetc() to a variable of type char. Plain char is compatible with either signed char or unsigned char. In order to make a distinction between a character and EOF (which is negative), the fgetc() function returns a character converted to unsigned char (or EOF). You need to test for EOF and then convert the value to a plain char.
The is...() function expects an int argument whose value is in the range of an unsigned char or EOF. If you have a plain char, you first have to cast it to unsigned char, or you can pass the return value of fgetc() straight to isalpha().
You attempt to append an zero-length char array (temp) to an uninitialized char array (s), and you do not test if there is enough room in the target array. This is broken for more reasons than than I care to enumerate.
You allocate memory for an array of 1000 pointers to char, but you never allocate memory for the char pointers themselves.
You try to append your buffer (s) to an uninitialized pointer (*tmp).
You call strlen() on something that is not null-terminated.
You never return the length of the array.
You call a number of functions that have not been declared.
This will read the file, put each word in an array
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char** getWords(char* filename, int* pn){
char input[100]; // array to hold each word
char** tmp; // double pointer
int counter = 0;
int words = 0;
int c;
tmp = malloc( (*pn)*sizeof(char*)); // allocate pointers for number of words
if ( tmp == NULL) {
printf ( "malloc failed\n");
exit (1);
}
FILE* fileInput = fopen(filename, "r");
if(fileInput == NULL){
printf ( "file open failed\n");
*pn = 0; // no words entered
return tmp; // return if file open fails
}
while(( c = fgetc(fileInput)) != EOF){
if( isalnum(c)){ // is alpha or number
input[counter] = c; // save to array
input[counter + 1] = '\0'; // save a \0 to the end to make a string
counter ++;
}
else{ // not alpha or number
if ( counter > 0) { // if there are characters, save the word
tmp[words] = malloc ( strlen ( input) + 1); // memory for this word
strcpy ( tmp[words], input); // copy the word to the array
words++;
counter = 0;
if ( words >= *pn) { // got all the words wanted
break;
}
}
}
if(counter > 98){ // too many characters for input, start a new word
tmp[words] = malloc ( strlen ( input) + 1);
strcpy ( tmp[words], input);
words++;
counter = 0;
if ( words >= *pn) {
break;
}
}
}
fclose(fileInput); // closing file
*pn = words; // save number of words
return tmp;
}
int main(int argc, char* argv[]){
int n;
int i;
printf ( "enter the number of words to obtain\n");
scanf ( "%d", &n);
char** a = getWords("opdracht_4_5.c", &n);
if (a != NULL){
puts("gevonden woorden:");
for ( i = 0;i < n; i++){
printf("%3d %s\n",i,a[i]);
}
for ( i = 0;i < n; i++){
free(a[i]); // free each word
}
free(a); // free the pointer to the words
}
return (EXIT_SUCCESS);
}
The input file I used had these as the first two lines
#include<stdio.h>
#include<string.h>
I get this output:
enter the number of words to obtain
6
gevonden woorden:
0 include
1 stdio
2 h
3 include
4 string
5 h
This answer is as yet incomplete
Please allow me to finish this before commenting on it -- Thank you
There are a lot if issues with your code, I won't clean it up for you. However I would like to give you some hints on how your program SHOULD be coded:
Your main objective is to read a file and load the content word by word in an array.
Sorting is an incorrect use because that implies you want to sort them alphabetically or in some other order after loading it into an array.
Okay, so first things first, let's figure out the overall operation of our program. We'll call our program kitten, because it's not quite as powerful as cat.
To run our program we will assume that we give it the filename we want to read on the command-line as follows:
$ ./kitten somefile.txt
and expect the output to be:
word1
word2
word3
.
.
.
wordN
Total words: N
So, let's get started, first we make sure that our user specifies a filename:
#include <stdio.h>
int usage(const char *progname);
int main(int argc, char *argv[])
{
if (argc < 2) {
usage(argv[0]);
return -1;
}
return 0;
}
int usage(const char *progname)
{
fprintf(stderr, "Usage is:\n\t%s filename\n", progname);
}
Now that we know that our program can get a filename, let's try to open the text file, if there is an issue with it we use perror to display the error and exit the program, otherwise we are ready to use the file:
#include <stdio.h>
#include <errno.h>
int usage(const char *progname);
int main(int argc, char *argv[])
{
FILE *fp;
if (argc < 2) {
usage(argv[0]);
return -1;
}
fp = fopen(argv[1], "r");
if (!fp) {
perror(argv[1]); /* display system error, with the filename */
return -1;
}
/* TODO: file manipulation goes here */
fclose(fp); /* close the file */
return 0;
}
int usage(const char *progname)
{
fprintf(stderr, "Usage is:\n\t%s filename\n", progname);
}
Now in C each function should perform just one task. The task should make human sense. For example if the function is supposed to read words into an array, then that's all it should do, it should not open a file or close a file, which is WHY the code above does not create a function for opening the file the way you did. Your function should take in FILE * as the file to read.
Because we use the FILE * as input we'll start the function name with an f to keep with the stdio convention. Ideally, the function should take a pointer to char * (strings) to store the words in.
#include <stdio.h>
#include <errno.h>
int usage(const char *progname);
size_t fload(FILE *fp, char **wordlist_p);
int main(int argc, char *argv[])
{
FILE *fp;
if (argc < 2) {
usage(argv[0]);
return -1;
}
fp = fopen(argv[1], "r");
if (!fp) {
perror(argv[1]); /* display system error, with the filename */
return -1;
}
if(fload(fp, wordlist_p) < 0) {
fprintf(stderr, "Something went wrong\n")
}
fclose(fp); /* close the file */
return 0;
}
int usage(const char *progname)
{
fprintf(stderr, "Usage is:\n\t%s filename\n", progname);
}
size_t fload(FILE *fp, char **wordlist_p)
{
size_t rv = -1; /* return value */
return rv;
}
Now we run into a conceptual problem. How do we allocate memory for wordlist_p? I mean we don't have any idea about how big the file is, we also don't know how big the biggest word in the file is.
Crude approach
Let's first try an think about it the simple way:
Point to the beginning of the `wordlist_p` with a `tail_pointer`
Read the file line by line, (we assume no hyphenation)
For each line split the line up along white spaces,
Allocate space for the number of words in the `wordlist_p` array
For each word in the split line
Allocate space for the word itself
Save the pointer to the word at the tail_pointer
Advance wordlist_p tail_pointer
Next word
Next Line
Let's look at what the fload function would look like with these steps above,
More to come ##

Print all words and their count

I'm to print all words and their count of a text file. When it reads the same word a second time it outputs the number zero. I can't figure out how to output the correct value. For example, if it found "and" it would print "and: 1" but when it finds "and" again it prints "and: 0".
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "hashMap.h"
int main (int argc, const char * argv[]){
char* word;
int *value = 0;
const char* filename;
struct hashMap *hashTable;
int tableSize = 10;
clock_t timer;
FILE *fileptr;
if(argc == 2)
filename = argv[1];
else
filename = "input1.txt"; /*specify your input text file here*/
printf("opening file: %s\n", filename);
fileptr = fopen(filename, "r");
if(fileptr != 0){
printf("Open Successfull!\n");
}
else{
printf("Failed to open!\n");
}
timer = clock();
hashTable = createMap(tableSize);
/*... concordance code goes here ...*/
while(1){
word = getWord(fileptr);
if(word == NULL){
break;
}
value = (int*)atMap(hashTable, word);
if(value != NULL){
value++;
}
else{
value = (int *) malloc(sizeof(int));
*value = 1;
insertMap(hashTable, word, value);
}
printf("%s:%d\n", word, *value);
}
}
The value you're fetching from the hashtable is a pointer to a block of memory with a single integer. You then increment the pointer, which makes it point to uninitialized memory, which just happens to have a zero in it. You probably want to increment the integer value, not the pointer.
Value is a pointer to an int. You don't want to increment the pointer, but rather increment the int it points to. Change value++ to (*value)++.

Program to read words from a file and count their occurrence in the file

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

Resources