Checking contents of char array in C - c

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 */
}

Related

opening file with fopen,c\ubuntu

Im trying to open file with fopen,and to read\write for "huffman tree".
After i've finished reading from the text, I tried to write in another file a "dictionary" that say what is the code for every letter.
I've got an eror that i havnt find something similar except that the reason is old version of eclipse, but it wasn't the problam.
Im programing in c with eclipse in ubuntu.
the main is look like:
int main(){
FILE *fsrc;
node *root;
if( (fsrc = fopen( "src.txt", "r" )) == NULL ){ //
printf( "The file 'src.txt' was not opened\n" );
return 0;
}
else {
printf( "The file 'src.txt' was opened\n" );
}
root = getBinTree(fsrc);
printTree(&(*root));
huffman(root);
return 0;
}
this is the function that writing to to target text
void printhtree(node *n,FILE *trg){
char *str = calloc(1, sizeof(char));
node *ptr=n;
while (!(ptr->m_hls && ptr->m_hrs)){
while(ptr->m_hls){
n=ptr;
ptr = ptr->m_hls;
str = realloc(1,sizeof(char)*(strlength(str)+1));
*(str+strlength(str)-1)='0';
}//while
if(!(ptr->m_hrs)){
printf("%s-%c ",str,ptr->m_ch);
n->m_hls = NULL;
return;
}//if
while(ptr->m_hrs){
n=ptr;
ptr = ptr->m_hrs;
str = realloc(1,sizeof(char)*(strlength(str)+1));
*(str+strlength(str)-1)='1';
}//while
}//while
if (!(ptr->m_ch)){
fputc(ptr->m_ch,trg);
fputc(' ',trg);
fputs(str,trg);
n->m_hls = NULL;
return;
}//if
}//printhtree
and this is the function that activate |pringhtree" function:
‪void drawTree(node *n,FILE *trg‬‬){
while(!(n))
printhtree(n,trg);
}
the error is on the first line of draw tree :
"void drawTree(node *n,FILE *trg‬‬)"
and it says:
"multiple markers at this line
bad character sequence encountered
stray '\252' in program, and the same line with the numbers 254,342,200.
there is the same error also where i wrote the names of all the function in the beginning of the program.
thank you very much
This is an important issue in your code
str = realloc(1,sizeof(char)*(strlength(str)+1));
For many reasons
The syntax is wrong, as it is you are realloc()ing the address 0x01.
You should not immediately overwrite the pointer, because if an error occurs then you will be unable to recover, a good usage of realloc() would be like
void *tmp = realloc(str, 1 + strlength(str));
if (tmp != NULL)
str = tmp;
This is not wrong, but it makes your code unnecessarily ugly, sizeof(char) is guaranteed to be 1.
Presumably strlength() emulates strlen(), so you don't want to compute the length twice, store it and use the value.
You allocate space the first time with malloc() but you drop that pointer completely because of the misuse of realloc() in your code, moreover you don't really need to allocate space except before writing to the pointed data, so you can replace your realloc() with malloc() and remove the calloc(), which by the way unnecessarily initialized all the values to 0, you don't need that.
You only initialize the last value of str which is set to '\0', but the rest of the data remains uninitialized because the function that would actually be allocating memory would be realloc() if it were used correctly, specially since calloc() is allocating a single byte.

C: cant access elements from an array of string in a struct

I am new to C and I don't fully understand all this pointer and memory allocation stuff, so sorry if I am conceptually wrong. I am trying to access string elements in an array of strings, but the array of strings is located in a struct, and every time I try to access it my program crashes.
I am getting an error when I try to do this if statement check
if (strcmp(functionList[holder].otherServers[i], "") == 0)
I just want to check if the current structure element in the array of structs (functionList[holder]) has a empty value filled for its elements in its array of strings (otherServers[i]). And when it finds its first empty element, all I want to do is copy a string in that index of the array of strings (otherServers[i])
And here is my code (note: I took out a lot of the code I thought was irrelevant for the question)
struct function {
char name[20];
int parameterNumer;
int canDo;
//currently the system has a 10 server max. You can change this easily
char *otherServers[10];
};
//global scope variables
//currently the system has a 10 server max. You can change this easily
char *serverList[10];
struct function functionList[10] = {{"",0, 0, {}}};
int numberofOtherServers;
while(strcmp(functionList[i].name, "") != 0 && i != -1)
{
//if the function exist in the functionList already, then just add server to the functions list of capable servers
if(strcmp(functionList[i].name, functionName) == 0 && functionList[i].parameterNumer == functionParam)
{
holder = i;
//function found so go through the functions list of servers and add it to the list
i = 0;
while(i >= 0)
{
if(strcmp(functionList[holder].otherServers[i], "") == 0)
{
strcpy(functionList[holder].otherServers[i], serverHelloName);
i = -1; //
}
if(i == 9)
{ //ran through entire list of all possible servers and couldnt find an empty slot
printf("server list full, should allow more room for other servers");
fflush(stdout);
i = -1;
}
}
printf("yay");
fflush(stdout);
}
if(i == 9)
{ //ran through entire list of all possible functions and did not see an empty slot or there is no match
printf("function list full so could not add, and there was no match for any functions");
fflush(stdout);
i = -1;
}
i++;
}
Your code does not show allocation of otherServers. When you have an array of character pointers, like otherServers, you need to allocate memory for each of the strings so there is something to point to.
This means you need to check the pointer points somewhere valid before you can do this strcmp() and strcpy():
if(strcmp(functionList[holder].otherServers[i], "") == 0) {
strcpy(functionList[holder].otherServers[i], serverHelloName);
i = -1;
}
Instead this snippet will check that otherServers[i] hasn't already been allocated and then allocate enough memory to store the string:
if ( functionList[holder].otherServers[i] == NULL ) {
// add one for the terminator
functionList[holder].otherServers[i] = malloc(strlen(serverHelloName) + 1);
// make sure the allocation worked
if ( functionList[holder].otherServers[i] == NULL ) {
// something went wrong so bail
break;
}
strcpy(functionList[holder].otherServers[i], serverHelloName);
}
When you have finished with otherServers[] or functionList[] itself, you need to free the memory allocated earlier:
for ( i = 0; i < 10; i++ ) {
if ( functionList[holder].otherServers[i] != NULL ) {
free(functionList[holder].otherServers[i]);
functionList[holder].otherServers[i] = NULL;
}
}
It's better to put a NUL in place of a plain "" in an initializer:
struct function functionList[10] = {{{'\0'},0, 0, {}}};
To check whether the name in your example is then assigned or not, you just dereference it and check for the NUL character:
*functionList[i].name == '\0'
strcmp checks for a nul character (aka zero-terminator), beginning at the offset supplied, and will keep going beyond the array if it doesn't find one - resulting in undefined behaviour, most likely an access violation, depending on how this buffer was allocated.
SpacedMonkey beat me to the remainder of the valid answer; you need to allocate storage for a string. By default a pointer just points to some area in memory - you must allocate it by hand with malloc before using it, and release it using free.

C: Passing a variable to a function gives wrong return

I am using some C with an embedded device and currently testing some code to read file details from an SD card. I am using a proprietary API but I will try to remove that wherever possible.
Rather than explaining, I will try to let me code speak for itself:
char* getImage() {
int numFiles = //number of files on SD card
for(int i=0; i<numFiles;i++) {
\\lists the first file name in root of SD
char *temp = SD.ls(i, 1, NAMES);
if(strstr(temp, ".jpg") && !strstr(temp, "_")) {
return temp;
}
}
return NULL;
}
void loop()
{
\\list SD contents
USB.println(SD.ls());
const char * image = getImage();
if(image != NULL) {
USB.println("Found an image!");
USB.println(image);
int byte_start = 0;
USB.print("Image Size: ");
**USB.println(SD.getFileSize(image));
USB.println(SD.getFileSize("img.jpg"));**
}
The two lines at the bottom are the troublesome ones. If I pass a literal string then I get the file size perfectly. However, if I pass the string (as represented by the image variable) then I am given a glorious -1. Any ideas why?
For clarity, the print out of image does display the correct file name.
EDIT: I know it is frowned upon in C to return a char and better to modify a variable passed to the function. I have used this approach as well and an example of the code is below, with the same result:
char * image = NULL;
getSDImage(&image, sizeof(image));
void getSDImage(char ** a, int length) {
int numFiles = SD.numFiles();
for(int i=0; i<numFiles;i++) {
char *temp = SD.ls(i, 1, NAMES);
if(strstr(temp, ".jpg") && !strstr(temp, "_")) {
*a = (char*)malloc(sizeof(char) * strlen(temp));
strcpy(*a, temp);
}
}
}
EDIT 2: The link to the entry is here: SD.ls and the link for the file size function: SD.getFileSize
From the return, it seems like the issue is with the file size function as the return is -1 (not 0) and because a result is returned when listing the root of the SD.
Thanks!
UPDATE: I have added a check for a null terminated string (it appears that this was an issue) and this has been addressed in the getSDImage function, with the following:
void getSDImage(char ** a, int length) {
int numFiles = SD.numFiles();
for(int i=0; i<numFiles;i++) {
char *temp = SD.ls(i, 1, NAMES);
if(strstr(temp, ".jpg") && !strstr(temp, "_")) {
*a = (char*)malloc(sizeof(char) * strlen(temp));
strncpy(*a, temp, strlen(temp)-1);
*a[strlen(*a)-1] = '\0';
}
}
}
This seems to work and my results to standard output are fine, the size is now not shown as the error-indicating -1 but rather -16760. I thought I should post the update in case anyone has any ideas but my assumption is that this is something to do with the filename string.
There are several things that could be wrong with your code:
1) You might be passing "invisible" characters such as whitespaces. Please make sure that the string you are passing is exactly the same, i.e. print character by character including null termination and see if they are the same.
2) The value that is getting returned by API and latter used by other API may not be as expected. I would advise that (if possible) you look at the API source code. If you can compile the API itself then it should be easy to find the problem (check what API getFileSize() gets from parameters). Based on the API documentation you have sent check the value stored in buffer[DOS_BUFFER_SIZE] after you get -1 from.
EDIT (after looking at the API source code):
On line 00657 (func find_file_in_dir) you have:
if(strcmp(dir_entry->long_name, name) == 0)
it seems as the only reason why you would have different reply when using string literal as opposed to the getting name from your function. So it is very likely that you are not passing the same values (i.e. you are either passing invisible chars or you are missing string termination).
As final note: Check the content of buffer[DOS_BUFFER_SIZE] before each code to SD API.
I hope this helps.
Kind regards,
Bo
This:
if(strstr(temp, ".jpg") && !strstr(temp, "_")) {
*a = (char*)malloc(sizeof(char) * strlen(temp));
strcpy(*a, temp);
}
is broken, it's not allocating room for the terminator and is causing a buffer overflow.
You should use:
*a = malloc(strlen(temp) + 1);
There's no need to cast the return value of malloc() in C, and sizeof (char) is always 1.

Problem using strstr function

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.

If-else problem

I'm learning queues and I came across this piece of code. It's from a book, so I can't post the whole code here but what I'm posting will be sufficient. More than a problem, I just want to confirm that whether my understanding of this code is correct or not.
In the function, delete_ap(), the 'if' statement calls qretrieve() function and stores its return value in pointer 'p'.
My problem is: If the value returned is not NULL, then too the 'if' statement is executed, isn't it?
So a value is still stored in 'p' and we can just print this value without using an 'else' statement as used in this example.
Thanks!
/* Delete an appointment from the queue. */
void delete_ap(void)
{
char *p;
if((p=qretrieve()) ==NULL) return;
printf("%s\n", p); <--Problem is in this line and the one above it.
}
/* Retrieve an appointment. */
char *qretrieve(void)
{
if(rpos==spos) /* spos:holds the index of the next free storage location.
rpos:holds the index of the next item to retrieve.*/
{
printf("No more appointments.\n");
return NULL;
}
rpos++;
return p[rpos-1];
}
This is the same as:
char *p = qretreive(); // <-- will always execute
if(p==NULL)
return; // <-- will not execute the next line if p is invalid
printf("%s\n", p);
The return statement is used instead of putting the rest of the function in an else block.
That is, the execution will only reach printf if p != NULL.
Note: Many people argue that returns in the middle of the code makes the code hard to read and prone to bugs due too missing cleanup that is usually done at the end of the method.

Resources