I'm having trouble using strstr. Here's what I have:
Passing character array of length 21 bytes to a function.
Traversing through nodes of a linked list, comparing each node's character array with the above array passed as mentioned in point 1
strstr is always returning NULL irrespective of any string passed
Let's say for example code like strstr("hello","he"). It should return pointer to "hello", but that never happens in my code below. It is always returns NULL.
Here is the code snippet of the program:
void display_to_file(const char *chr,c_uint32 pos_in_list,c_uint32 line_no)
{
NODE *search = ptrs_to_heads_of_alpha[pos_in_list];
char *chk;
char redundant[21]={'\0'};
int first=1;
uint32 count = 0;
while((NULL!=search) && (count<21))
{
printf("\nsearch->arg=%s",search->arg); /*for example search->arg is "hello"*/
/*above statement prints "hello"-correctly*/
/*for example chr="?he" */
printf("\nchr=%s",&chr[1]); /*prints "he" correctly*/
chk=strstr(search->arg,&chr[1]);
if(chk != NULL) /*is always null- not known why it returns null even for valid cases*/
{
printf("\nentered_\n");
++count;
if(1 == first)
{
fprintf(op_fp," %s\n",search->arg);
strcpy(redundant,search->arg);
printf("\nop:%s\n",search->arg);
first = 0; /*only for first node print*/
}
else
{
if(strcmp(redundant,search->arg) == 0)/*duplicate found*/
--count; /*need to search for one more item*/
else
{
fprintf(op_fp," %s\n",search->arg);
strcpy(redundant,search->arg);
}
}
}
else
printf("\nelse,else,else\n\n"); /*Always this statement is executed even
if I passed valid arguments*/
search=search->next;
}
}
is there any warning with this statement at compile time?:
chk=strstr(search->arg,&chr[1]);
2nd argument should be const char * in strstr()
make sure this thing.
One more thing try with this statement
chk=strstr(search->arg,"he");
one more thing check you have included string.h
#include<string.h>
Try embracing string with quotes (or another noticeable symbol), because there could be space characters, for example, which you don't see. So replace
printf("%s\n", some_string);
with
printf("\"%s\"\n", some_string);
I recommend to always use embracing with "printf-debugging". However, your problem could be somewhere else. Try to shorten your program for finding an error.
Related
I know some similar questions already exists but they did not help me in my case.
What I need to do is creating a table symbol for a compiler project using flex. Basically, I get a char* (a new identifier to add to the table symbol) that is then placed in a char[1000] array, that is my table symbol.
Everything works fine until I try to print my table symbol (called symbArray): when I'm trying to print symbArray[4] for ex., it also prints me symbArray[5] and symbArray[6], ... At this point, if you have any solutions, I'll take it.
What I tried to do to solve it is to use strcpy(intermediaryVariable, yytext) to convert my char* (called yytext) into a char[100] (intermediaryVariable). But this does not seems to work because now, symbArray[4] = symbArray[5] = symbArray[6] (see details later).
Here is my function that should add the symbol to the table after that I tried to solve the problem with strcpy():
void addSymbole(char text[100], int index) {
// findSymboleArray is a function to verify if our identifier does not already exist
// symbArray is the symbole array declare on a global scope as char* symbArray[1000];
if (findSymboleArray(text) == -1 && symbArray[index] == NULL) {
char textToCopy[100];
strcpy(textToCopy, text);
symbArray[index] = textToCopy;
printf("%s goes to index %i.\n", text, index);
}
}
Here is how I call my function addSymbole()
// newChar is the intermediaryVariable declared on a global scope as char newChar[100];
// symbArrayLength is declared as int symbArrayLength = 0; on a global scope too
strcpy(newChar, yytext);
addSymbole(newChar, symbArrayLength);
symbArrayLength += 1;
And here is how I print the content of my symbol table:
void printSymboleArray() {
for(int i = 0; i < 1000; i++) {
if(symbArray[i] == NULL) {
// so that the for-loop can be stopped
i = 1000;
} else {
printf("value of element at index %i: %s.\n", i, symbArray[i]);
}
}
}
Here is a part of result that I can get when I print the symbol table:
value of element at index 0: main.
value of element at index 1: char.
value of element at index 2: int.
value of element at index 3: float.
value of element at index 4: A878U_GH.
value of element at index 5: A878U_GH.
value of element at index 6: A878U_GH.
value of element at index 7: A878U_GH.
with symbols that are:
coucou
bogoss13_
BAD_CHAR
A878U_GHJ // note that in the result, the J is not printed and is sometimes replaced by random characters like '3' or 'c' for example when retesting the program
so that the expected result is:
value of element at index 0: main.
value of element at index 1: char.
value of element at index 2: int.
value of element at index 3: float.
value of element at index 4: coucou.
value of element at index 5: bogoss13_.
value of element at index 6: BAD_CHAR.
value of element at index 7: A878U_GHJ.
Please note that main, char, float and int are initialized with this function:
void initializeSymboleArray() {
// reserved names
symbArray[0] = "main";
symbArray[1] = "char";
symbArray[2] = "int";
symbArray[3] = "float";
symbArrayLength = 4;
}
To sum up, I would like to know how to properly convert a char* into a char[] so that such a problem that I get (all the elements in the indexes are equal to the last identifier detected) does not appear.
If there is another solution than converting a char* into a char[], I would be glad to hear it.
I hope this isn't too much confusing and I apologize in advance for the lack of clarity.
Thank you for reading me.
printf("%s", str) will print byte sequence pointed to by str until it reach a null ("\0") symbol. So my educated guess is, your original problem was because you did not null-terminated your strings. The strcpy function will automatically null terminate the result (as stated in the manual).
Your new solution has a memory management issue. In addSymbole function you define a buffer called textToCopy then use strcpy to place the string in that buffer. Afterwards you proceed and add a pointer to this buffer in your table (symbArray[index] = textToCopy;). Because this buffer is allocated on the stack, it would be poped (removed) when the function returns (the buffer gets out of scope). So the pointer is no longer valid.
I guess the reason why you see all the indexes have the same value is because the same memory is reused when you again call the addSymbole function. You can verify this by checking the memory address (print("%p\n", &symbArray[i])).
You can use malloc for reserving some memory on the heap. When you allocate memory from heap it would stay there until you explicitly free that (using free function).
If I want to modify your code I would rewrite your addSymbole function like shown below.
void addSymbole(char text[100], int index) {
// findSymboleArray is a function to verify if our identifier does not already exist
// symbArray is the symbole array declare on a global scope as char* symbArray[1000];
if (findSymboleArray(text) == -1 && symbArray[index] == NULL) {
char *textToCopy = malloc(100); // allocate a buffer with enough size.
if (!textToCopy) { // If malloc failed to reserve memory it returns NULL
// Hanlde the error here
}
strcpy(textToCopy, text);
symbArray[index] = textToCopy;
printf("%s goes to index %i.\n", text, index);
}
}
I also want to warn you about the line you are copying yytext to a buffer. strcpy copies characters of the string until reaching "\0".
strcpy(newChar, yytext);
If yytext is not null-terminated then it would cause issues. You could at least use strncpy so that your newChar don't overflow.
char *strncpy(char *dest, const char *src, size_t n);
UB (undefined behaviour). You assign symbArray[index] = textToCopy; pointer with address of the automatic variable textToCopy and this variable stops to exists when the function returns.
char *addSymbole(const char *text, const size_t index)
{
if (findSymboleArray(text) == -1 && symbArray[index] == NULL)
{
symbArray[index] = malloc(strlen(text) + 1);
if(symbArray[index])
{
strcpy(symbArray[index], text);
}
printf("%s goes to index %i.\n", text, index);
}
return symbArray[index];
}
So I declared an array of strings as
typedef char String[11]; and in my main function I have this condition
`
char word[12];
String hashArray[SIZE];
if (insertword(word, hashArray) == 1)
printf("word %s successfully inserted.\n", word);
This is the function that it calls.
int insertword(char word[], String hashArray[])
{
//get the hash
int hashIndex = hashfunction1(word)% 7 ;
printf("INDEX:%d\n", hashIndex); //delete later
if (hashArray[hashIndex] == NULL) //ERROR IS HERE
{
strcpy(hashArray[hashIndex], word);
printf("INSERTED!! ");
return 1;
}
else
{
printf("NOT INSERTED!! ");
return 0;
}
}
I have tested my program by adding a print and apparently the error happens at the first conditional statement. The else part is always what gets executed. I'm definitely missing something here, any help would be appreciated.
The problem with your code:
char word[12];
String hashArray[SIZE];
word is not initialized, hence it has garbage values.
Then inside insertword function:
int hashIndex = hashfunction1(word)% 7;
The array "decays" into a pointer to the first element:
hashfunction1(word)%7;
Is just as:
hashfunction1(word[0])%7;
When again, word is not initialized, so the value will be put in hashIndex is unknown!
Then you are accessing the array hashArray[hashIndex] in that index which is unknown, might be out of boundary.
Accessing an array outside its bounds has "undefined behavior".
To fix this, you need to put some random values in word array which will be smaller than 32, as stated in your comment, size = 32.
I have the following structure and have some code to use it below. The control is not going into the if statement(I need to check if the chat_info[queue].message is empty which it is)
struct chat{
char message[MAXNAME];
int client;
int group;
int flag;
};
.
.
.
.
if(filedata.data==NULL)
{
printf("\n data is %s",filedata.data);} //displays "data is "
chat_info[queue].message[0]='\0'; //setting 0 before copying data
strcpy(chat_info[queue].message,filedata.data);
printf("\n data is %s",chat_info[queue].message);//displays "data is "
if(chat_info[queue].message[0]=='\0'){
// not going into this if statement
//I also tried if(chat_info[queue].message== "") and if(chat_info[queue].message== NULL)
}
The first issue I see:
if (filedata.data == NULL)
Which can also be written as:
if (!filedata.data)
Once inside the if-statement you attempt to copy the contents of filedata.data into chat_info[queue].message. However, we previously established that filedata.data points to nothing. It is NULL. Using strcpy() with a NULL pointer as the source should not work.
Perhaps you meant:
if (filedata.data != NULL)
Which can also be written as:
if (filedata.data)
Secondly, if filedata.data wasn't NULL, think about when chat_info[queue].message[0] == '\0' would be true.
strcpy(chat_info[queue].message, filedata.data);
if(chat_info[queue].message[0] == '\0') {
// Message was determined to be empty.
}
It would only be true if the filedata.data was an empty string. (Note: this is different than being NULL!) Is that what you want? If so, the current code should work fine.
Reference: strcpy() documentation
What is the type for message? Because, if it is a string, then it will implicitly cast when you set it to a char = '\0';. Perhaps, you need to do:
if (chat_info[queue].message[0] == "\0")
strcpy(chat_info[queue].message,filedata.data);
/* You have assigned some data for chat_info[queue].message
* in the above step assignment should be successful.
*/
if(chat_info[queue].message[0]=='\0')
/* How can message[0] be null? It will never be. Think of what you're
* trying to achieve with the condition.
* If you're checking for a non-empty message, then it should be
* chat_info[queue].message[0]!='\0'
*/
{
./* some stuff here */
}
Need "a"="e" if position is even and "a"="o" if position is odd. I'm new at pointers the program itself is easy to make put i don't understand how pointers work yet.
Heres the pointer.
void word(char *w[100])
{
int n=0;
while(*w[n]=='/0' && n<*w[n]){
if(*w[n]=='a' && n%2==0)
*w[n]='o';
else if(*w[n]=='a' && n%2!=0)
*w[n]='e';
}
n++;
}
When I did it without a pointer the program worked.
Heres the rest of the program.
void main(void)
{
char pr[100];
puts("Choose a word with letter a in it 'a' ");
scanf("%s", &pr);
word(pr);
printf("The changed word is %s", pr);
return 0;
}
How can I make the pointer to work and where did I make a mistake?
When you pass an array to a function, it actually passes a pointer to the first element. If the original array is <type> <name>[<size>], the corresponding type of the argument is <type>*, not <type>*[<size>]. char *w[100] means an array of 100 pointers to characters, not an array of 100 characters as pr is declared in main().
A pointer can be accessed using array notation: p[i] is equivalent to *(p+i). You don't use both array indexing and indirection (unless the array is an array of pointers, and you want to access what each element points to).
You also had your loop test wrong. You should loop as long as the current character of the string is not null, not while it is null, since the null character is at the end of the string. And the n < *w[n] test makes absolutely no sense at all.
So the function should be:
void word(char *w)
{
int n=0;
while(w[n] != '\0'){
if(w[n]=='a' && n%2==0) {
w[n]='o';
} else if(w[n]=='a' && n%2!=0) {
w[n]='e';
}
n++;
}
}
You can optionally declare a pointer argument using array notation, e.g.
void word(char w[])
But this is considered equivalent, it's still really a pointer that's passed. You can put an array size in there, but it's not used for anything.
I have an array of pointers (char**) which contain some strings. The array ends with an empty string ('\0'). I am supposed to search for a specific word in that array of strings and delete the whole line (ofc using realloc and shortening the array of strings). I'm having hard time doing this, I keep getting 'bad ptr' error.
My code:
void deleteSentence(char **text){
char *word,*fptr;
int i=0;
word=(char*)calloc(BUFFER,sizeof(char));
printf("Enter word to delete sentences:\n");
gets(word);
while(text[i][0]!='\0'){
char *str=(char*)malloc((strlen(text[i])+1)*sizeof(char));
strcpy(str,text[i]);
fptr=strtok(str,DELIM);
while(fptr!=NULL){
if(strcmp(fptr,word)==0){
int j=i;
while(text[j][0]!='\0'){
text[j]=(char*)realloc(text[j],(strlen(text[j+1]))*sizeof(char));
strcpy(text[j],text[j+1]);
j++;
}
free(text[j]);
}
fptr=strtok(NULL,DELIM);
if(fptr!=NULL)
i++;
}
}
}
Help much appreciated :)
You're leaking memory like a sieve leaks water, and overrunning your arrays in at least two places. Furthermore the integration of input with the functional purpose of this code does literally nothing to help. The function should do one thing and one thing only:
Given a pointer to an array of char* pointers terminated with an empty string (or NULL), delete all strings in the pointer array that contain word. The resulting potentially compacted array is the return value of the function.
Consider this:
char ** deleteSentances(char **text, const char *word)
{
char **dst = text, **src = text, **res = text;
size_t size = 1, deleted = 0;
// loop while we have a non-null string that isn't empty
while (*src && (*src)[0])
{
char *tmp = strdup(*src);
if (tmp == NULL)
{
perror("Failed to allocate tmp");
exit(EXIT_FAILURE);
}
char *token = strtok(tmp, DELIM);
// search for matching word
while (token && strcmp(word, token))
token = strtok(NULL, DELIM);
// if not found, keep the string. otherwise delete it.
if (!token)
{
*dst++ = *src++;
size++;
}
else
{
free(*src++);
++deleted;
}
// don't need this.
free(tmp);
}
// resize the original array (which could have only gotten smaller)
if (deleted > 0)
{
res = realloc(text, size * sizeof(*res));
if (res == NULL)
{
perror("Failed to allocate res");
exit(EXIT_FAILURE);
}
res[size-1] = *src;
}
return res;
}
Hopefully that explains enough. The code is called like this:
char **text, *word;
//... populate text with strings
//... populate word with prospect word
text = deleteSentances(text, word);
Memory Leaks O'Festival
The OP wanted to understand where memory leaks were in the original posted algorithm. Consider the following first and foremost: For every allocation, there should be a known point of free'ing that memory. This example is somewhat difficult to nail that concept down simply because you're bringing dynamic allocations to the function, and some of them are going to be kept.
That said, consider the following places of interest. We assume coming in to this that at some point we allocated a pointer-array of this form:
char **text = malloc(N * sizeof(*text));
I.e. we have N character points. In each of those, we further assume a dynamic allocation for a character string has also transpired:
for (int i=0; i<(N-1); ++i)
{
//... compute length of next string
text[i] = malloc(length * sizeof(**text));
//... copy in next string to text[i]
}
And finally, the last character pointer in the text array is either NULL or points to a dynamic string of length 0 (i.e. a 0-length terminated string).
Whew. Ok. after all of that lets look at your algorithm:
void deleteSentence(char **text)
{
char *word,*fptr;
int i=0;
// Leak 1: allocate a single buffer of BUFFER-length.
// this is never freed anywhere in this function
word=(char*)calloc(BUFFER,sizeof(char));
printf("Enter word to delete sentences:\n");
// Problem: gets() is so evil and bad it has been deprecated from
// the C langage and will not be available in the next release.
// use fgets() instead.
gets(word);
while(text[i][0]!='\0')
{
// Leak 2: Done N times, where N is the number of strings in
// your original array. again, this is never freed.
char *str=(char*)malloc((strlen(text[i])+1)*sizeof(char));
strcpy(str,text[i]);
fptr=strtok(str,DELIM);
while(fptr!=NULL)
{
if(strcmp(fptr,word)==0)
{
int j=i;
while(text[j][0]!='\0')
{
// Leak 3: Done M-N times for ever string we find in position
// M of the original array. This can be *huge* if there are
// a decent number of number of reductions that crunch your
// original array down.
text[j]=(char*)realloc(text[j],(strlen(text[j+1]))*sizeof(char));
strcpy(text[j],text[j+1]);
j++;
}
// Problem: this just freed the termination string, which should
// never be done. We now have undefined behavior for the rest
// of this algorithm since the terminatingg string is invalid.
free(text[j]);
// Problem: You shoud break right here. See below for why
}
// Problem: you're missing an else condition here. At this point
// if the strcmp() found a match there is no reason to continue
// the loop. You found a match and deleted the string, crunching
// all the other string down one slot in a most-inefficient
// memory-leaking algorihm.
fptr=strtok(NULL,DELIM);
// Problem: the logic here is completely wrong. The i in this case
// should be incremented OUTSIDE the inner while loop. Furthermore
// the test is backwards.
if(fptr!=NULL)
i++;
}
}
}
In short, if it were possible to leak more memory than you did in that algorithm, I'm hard pressed to see how. The posted code I provided will work given the confines of the description I presented, and should be carefully looked to, even stepped through with a debugger line-y-line, to better understand how it works.