Storing a text file lines into Array - c

ı am trying to take text from a file and store it into 2d array every line will be different row and every word will be different column i was thinking to store lines first then seperate words but this doesn't work quite right in the while loop its prints correctly but outside of the loop array only has last line any help?
char **arr;
arr=malloc(sizeof(int)*line);
int a ;
for(a=0;a<line;a++){
arr[a]=(char*)malloc(sizeof(int)*maxword);
}
int i=0;
rewind(fp);
while(fgets(command,count, fp)!=NULL) {
arr[i]=command;
printf("%s",arr[i]);
i++;
}

The problem here is the way you are trying to copy the input command string into your arr array of strings. The line you have:
arr[i]=command;
is assigning to the string pointer at arr[i] the value of the string pointer command, which is the start of the command string. When you then print this out inside the loop, it shows correctly, because you've just read in that string.
However, in each iteration of the loop, you are giving the 'next' arr[i] the same pointer (the start of the command string). So, when you then print out each arr[i] string when the looping has finished, each will point to the same string, which will have whatever value the last-read command was.
Instead, inside your loop, you should replace the above line with this:
strcpy(arr[i], command);
This will copy the contents of command to the string indexed by arr[i].
Try it and see! And feel free to ask for further clarification and/or explanation.
EDIT: Also, as pointed out by user3121023 in the comments, you need to release the memory you have allocated for arr but only when you are completey done using it! You can do this using calls to the free function, corresponding to each of your malloc calls:
for(a=0;a<line;a++){
free(arr[a]); // First, run through a loop freeing each row ...
}
free(arr); // ... and only then free the "array of row pointers!"
EDIT2: Oh, and I forgot! As pointed out by Bodo (thanks for the reminder) you must never assume that a pointer has any given size. You have:
arr=malloc(sizeof(int)*line);
which assumes that a pointer-to-char has the size of an int. It may do on some platforms, but don't ever rely on this. Use this instead:
arr=malloc(sizeof(char*)*line);

Related

How to delete a specific string from an array of strings in C?

I need a function that receives an array of pointers to strings and it's size.
Then it should seek for those strings which occur in the array more than once - then I have to delete them and realloc the array.
Function should return new size of the array.
I'm trying to solve this, and not sure what`s wrong.
I want to move each string, that I want to delete, to the end of the array and then delete it, but not sure when the "realloc" should happen.
#include<stdio.h>
#include<stdlib.h>
int DeleteString(char** tab, int n){
char* check=malloc(sizeof(char)*100);
int deleted;
int i,j,g,h;
for(i=0;i<n;i++){
strcpy(check, tab[i]);
for(j=0;j<n;j++){
if(strcmp(check, tab[j]) == 0){
deleted++;
char* temp = malloc(sizeof(char)*100);
for(h=j;h<n-1;h++){
strcpy(temp, tab[h+1]);
strcpy(tab[h+1], check);
strcpy(tab[h], temp);
}
}
if(deleted>0){
realloc(tab, sizeof(char*)*(n-deleted));
}
}
}
return n-deleted;
}
For now there is "Segmentation fault" error
Oops, your code contains numerous problems, because you failed to observe some major rules of C language:
every non static variable shall be initialized (what about deleted?)
any object that was malloced shall be freed (what about check and temp.)
never change something that was passed as an input parameter to a function, or do not expect the change to be visible on return (tab has to be considered here because of next line).
allways assign the result of realloc because it can be different from the input pointer (realloc(tab, sizeof(char*)*(n-deleted));).
The first one is probably the cause of the segmentation fault because as deleted is unitialized its value is just undeterminated. But all problems should be fixed.
The reason for the SEGMENTATION FAULT is tab[0] store the address of the variable which stores the actual string.
Here tab[i] is in for loop,hence when it tries to fetch tab[1] itself memory error.
for(i=0;i<n;i++){
strcpy(check, tab[i]);...}
FOR EXAMPLE:
char *foo = "something";
char **ptr2;
ptr2 = &foo;
printf("check = %s", *ptr2);
for(int i=0;i<9;i++){
printf(" check = %c", ptr2[i]);
}
Output
check = something check = 4check = �check = pcheck =
Actally it is an error.
First of all, don't forget to initialise variables like deleted, as it has been said in other answers.
Next, you are supposed to free memory (as you are deleting items) and you only call malloc(3)). That seems a little counter-common sense, doesn't it?
Third, you make a lot of string copying in the loops, while it should be more efficient just to move pointers up, so you don't need to realloc the string elements and copy the cell contents (by the way, are you sure those strings will be feed to the function as malloc()d strings? I will assume that as you do)
Fourth, consider sorting the array first, so all the similar strings will be adjacent in the array. This has a cost O(n*log(n)) that, appended to the delete next string if equal (with cost O(n)) makes total cost O(n*(log(n)+1)) or O(n*log(n)) and not O(n^2) which is your actual cost)
Once sorted, only the strings deleted should be free(3)d, the pointers moved back to the start of the array as holes get appearing, and finally(when all is finished) you can just realloc(3) the array of pointers (only once, not at every pass through the loop)
Remaking the example is out of the scope of this answer, as it looks actually some school exercise. Sorry for that. I'm sure that the other hints will help you to retry the exercise with more success.
And think: thinking before writing is how one succeeds in this job.

How can i copy part of a string to another variable?

Hi i am trying to figure out how to copy only part of a line being read from a text file. I want to copy a line from a file called fileLine to a variable called line. The problem is, is that i only want to copy starting at index 10 in fileLine but memcpy dislikes that. How can i change this to make memcpy happy?
int stringLength = 0;
stringLength = strlen(fileLine);
memcpy(line, fileLine[10], stringLength); //this is where things go wrong.
You have passed in a char type to something that expected a const void*. This would have been okay if you had passed it a char*. You can do that as either &fileLine[10] or fileLine + 10.
Since you are offsetting by 10, you also want to ensure you copy 10 fewer characters:
memcpy(line, &fileLine[10], stringLength-10);
Although you probably want to copy the string terminator too...
memcpy(line, &fileLine[10], stringLength-9);
Yuck!
Instead, you could use strcpy:
strcpy(line, fileLine + 10);
In all cases, make sure that line is an array or a pointer to memory that is actually allocated to your process.
You can use getline function to get part of the string. But first, you have to move your read pointer to the position from which you want to read using seekg function.
seekg(ios flag, bytes);
cin.getline(source, number of characters, ending character);

Issues printing whilst using getline()

I'm just having a bit of difficulty with a print. Basically, I have code and I'm assigning values to bestmatch[], which is defined as being of type line_t (see struct at bottom).
As you can see, I am storing values for bestmatch[].score (double), bestmatch[].index (int) and bestmatch[].buf (string). When I print them, show in second code block below, bestmatch[i].index and bestmatch[i].score print correctly; however, bestmatch[i].buf does not print at all.
Just to confuse matters more (for myself at least), if I print bestmatch[i].buf at the end of scorecmp (first code block), it prints fine. I've got my call to scorecmp down the very bottom for reference.
Why is it that it is printing index and score fine, but not buf? Or even more, how can I fix this behaviour?
Thank you for your help! Please let me know if you need any additional information
The print, appearing in main, is as follows (for reference, TOP_SCORING_MAX is the number of elements in bestmatch[]):
int i;
for (i = 0; i<TOP_SCORING_MAX; i++) {
if (bestmatch[i].score != -1) {
printf("line\t%d, score = %6.3f and string is %s \n",
bestmatch[i].index,bestmatch[i].score, bestmatch[i].buf);
}
}
And in case you would like the struct:
typedef struct line_t {
char* buf;
int lineLength;
int wordCount;
int index;
double score;
} line_t;
This is my call to scorecmp:
scorecmp(linePtr, bestmatch);
You need to copy the content of the strings, not just the pointers, because they seem to be destroyed, freed, or mutilated before you print them:
bestmatch[j].buf = strdup(linePtr->buf);
Don't forget to free the copied string at the end.
The getline function is the preferred method for reading lines of text from a stream.
The other standard functions, such as gets, fgets and scanf, are a little too unreliable.
The getline function reads an entire line from a stream, up to and including the next newline character.
This function takes three parameters:
A pointer to a block of memory allocated with malloc or calloc. This parameter is of type char**, and it will contain the line read by getline when the function returns.
A pointer to a variable of type size_t. This parameter specifies the size in bytes of the block of memory pointed to by the first parameter.
The stream from which to read the line.
The first parameter - a pointer to the block of memory allocated with malloc or calloc - is merely a suggestion. Function getline will automatically enlarge the block of memory as needed via realloc, so there is never a shortage of space - one reason why this function is so safe. Not only that, but it will also tell you the new size of the block, by updating the value returned in the second parameter.
That being said, every time you call function getline, you first need to:
Set maxSz to a reasonable size.
Set line.buf = malloc(maxSz).
Set the value of maxSz not too large, in order to reduce the amount of redundant memory used.
Set the value of maxSz not too small, in order to reduce the number of times getline calls realloc.

Malloc, realloc, and returning pointers in C

So I am trying to get information from an html page. I use curl to get the html page. I then try to parse the html page and store the information I need in a character array, but I do not know what the size of the array should be. Keep in mind this is for an assignment so I won't be giving too much code, so I am supposed to dynamically allocate memory, but since I do not know what size it is, I have to keep allocating memory with realloc. Everything is fine within the function, but once it is returned, there is nothing stored within the pointer. Here is the code. Also if there is some library that would do this for me and you know about it, could you link me to it, would make my life a whole lot easier. Thank you!
char * parse(int * input)
{
char * output = malloc(sizeof(char));
int start = 270;
int index = start;
while(input[index]!='<')
{
output = realloc(output, (index-start+1)*sizeof(char));
output[index-start]=input[index];
index++;
}
return output;
}
The strchr function finds the first occurrence of its second argument in its first argument.
So here you'd have to find a way to run strchr starting at input[start], passing it the character '<' as second argument and store the length that strchr finds. This then gives you the length that you need to allocate for output.
Don't forget the '\0' character at the end.
Use a library function to copy the string from input to output.
Since this is an assignment, you'll probably find out the rest by yourself ...
That is the dynamic reading:
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
int main(){
int mem=270;
char *str=malloc(mem);
fgets(str,mem,stdin);
while(str[strlen(str)-1]!='\n'){//checks if we ran out of space
mem*=2;
str=realloc(str,mem);//double the amount of space
fgets(str+mem/2-1,mem/2+1,stdin);//read the rest (hopefully) of the line into the new space.
}
printf("%s",str);
}
Your output needs to end with '\0'. A pointer is just a pointer to the beginning of the string, and has no length, so without a '\0' (NUL) as a sentinel, you don't know where the end is.
You generally don't want to call realloc for every individual new character. It would usually make more sense to malloc() output to be the strlen() of input and then realloc() it once at the end.
Alternatively, you should double it in size each time you realloc it instead of just adding one byte. That requires you to keep track of the current allocated length in a separate variable though, so that you know when you need to realloc.
You might read up on the function strcspn, it can be faster than using a while loop.

Array Elements Overwritten with Last in C

I'm trying to create a program which takes in a set number of strings (the user is asked to put in the number of strings they will enter), once it has these strings, they are placed in an array, using dynamic memory.
The ouput would be something like this:
# of Strings: 3
Cat
Dog
Elephant
Cat
Dog
Elephant
Heres a snippet of my code, after I have the number of strings.
sptr=malloc(sizeof(char*)*nStrings);
for(i=0;i<nStrings;i++)
{
scanf("%s",string);
length=strlen(string);
sptr[i]=malloc(sizeof(char)*length);
sptr[i]=string;
}
Where sptr is the array I'll access to output the strings.
So it's an array of pointers which then point to individual strings (or other arrays of characters, if you'd prefer to think of it that way).
Lets say there are two strings.
I allocate memory for two pointers,
Then in the first pointer, i scan in a string,
i find the length of the string,
i allocate memory the size of the string
and i equal the pointer to the string.
This all works dandy, and if I were to put a printf() right after that last line, it will work.
The problem i face is, if lets say there are 3 strings, each time through sptr[i] is assigned correctly, but then outside of that block, all of the indicies of sptr are = to the last string i put in, and I have no idea why.
If you could help me out I'd appreciate it. Thanks.
sptr=malloc(sizeof(char*)*nStrings);
for(i=0;i<nStrings;i++)
{
scanf("%s",string);
sptr[i]=strdup(string);
}
I assume the variable string has enough memory to keep the read strings.
The error occured because you set the pointer to point to the string variable.
You need to allocate 1 character extra for the null terminator:
sptr[i]=malloc(sizeof(char)*(length+1));
Also, you need to copy the string into the newly allocated memory:
strcpy(sptr[i], string);
There are 2 problems in your code: you don't allocate enough memory. Should be length + 1 because of the ending \0 in a string. Secondly you should use strcpy to copy the string to your allocated memory. Lookup the strdup function that handles both.
strlen doesn't account for the zero termination, you need to add one. But mainly you need to copy the string into the memory you allocate.

Resources