Hi for some reason Strcat does not like the value property within my structure. I'm not sure why. Here is my structure code:
typedef struct TrieSearchTree{
char value;
struct DynamicList* children;
};
and here is my method:
void PrintDynamicListContents(struct DynamicList* dynamicList, char* word)
{
struct dynamicListNode* currentRecord;
struct TrieSearchTree* trieSearchTree;
struct dynamicListNode* nextRecord = dynamicList->head;
while(nextRecord != NULL)
{
currentRecord = nextRecord;
nextRecord = currentRecord->next;
trieSearchTree = currentRecord->entity;
if (trieSearchTree != NULL)
{
if (trieSearchTree->value != WORD_END_CHAR)
{
char c[CHAR_LENGTH] = "";
strcat_s(c, CHAR_LENGTH, word);
strcat_s(c, CHAR_LENGTH, trieSearchTree->value);
PrintDynamicListContents(currentRecord, c);
}
else
{
printf("%s", word);
}
}
}
}
Here is the error message:
Proof that the value from the structure returns something (the 'l' character)
I've been trying to get strcat working for hours and I can't get it to work even reading the online tutorials. All help appreciated.
The strcat_s function expects a char *, specifically a pointer to a null terminated string, as the third argument. You're passing in a single char. Your compiler should have warned you about this.
That character is being interpreted as a pointer and being dereferenced. This invokes undefined behavior, which in this case manifests in a crash.
If you want to append a single character to a string, you need to add it and a new null terminator manually.
char c[CHAR_LENGTH] = "";
strcat_s(c, CHAR_LENGTH, word);
c[strlen(c) + 1] = '\0';
c[strlen(c)] = trieSearchTree->value;
Related
I've got an issue i can't handle so i've thought maybe you can help me. Basically i have a function that receives a char* as a paramater and does some stuff to it(i've checked those steps/functions and they work just fine).If the char* given in the function is ""(i guess NULL), i receive seg fault with assert.
Here is the code:
char *computeRNA(char *s)
{
if (s != NULL && s!= "")
{
Lista* l = to_list(s);
int i;
l = l->next;
for(i = 0; i<= lungime(l); ++i)
{
if(l->info == 'T')
l->info = 'U';
l = l->next;
}
char *rna = to_pointer(l);
return rna;
}
return NULL;
}
And here is the assert:
char *s;
s = computeRNA("");
ASSERT(!strcmp(s, ""), "computeRNA-01");
free(s);
This is a school homework so i can not change assert's code , only the function.Thanks in advance !
This ASSERT that you weren't supposed to be changing, tests that if an empty string is given to computeRNA it should also return an empty string:
s = computeRNA("");
ASSERT(!strcmp(s, ""), "computeRNA-01");
Your code returns null pointer. Also comparing strings needs to be done using strcmp, s == "" would only compare pointer values that wouldn't be of use here.
Thus I'd start the function with
// null pointer was given
if (!s) {
return calloc(1, 1);
}
// an empty string was given (the first character pointed to b s is the string terminator.)
// to compare explicitly, you need to do `strcmp(s, "")` == 0. `s == ""` is wrong.
if (!*s) {
return "";
}
You cannot pass a NULL pointer to strcmp() as argument. Before the ASSERT statement, just check for non-NULL value of s. Something like
if (s) {
ASSERT(!strcmp(s, ""), "computeRNA-01");
}
should do the job.
EDIT:
In case changing the function using the assertion is also not possible, you can modify the computeRNA() function to return an empty string, instead of NULL, like
char * empty_string = calloc(1,1);
return empty_string;
which can later be passed to free() in the caller.
I want to pass the glist pointer to the function so that I can get the changed value in main function.
I have code as:
#include <stdio.h>
#include <string.h>
#include <glib.h>
char *col_trim_whitespace(char *str)
{
char *end;
// Trim leading space
while(isspace(*str)) str++;
if(*str == 0) // All spaces?
return str;
// Trim trailing space
end = str + strlen(str) - 1;
while(end > str && isspace(*end)) end--;
// Write new null terminator
*(end+1) = 0;
return str;
}
void line_parser(char *str,GSList* list1)
{
GSList* list = NULL;
char *token, *remstr=NULL ;
token = strtok_r(str,"\n",&remstr);
while(token != NULL)
{
if(token[0] == ' ')
{
token = col_trim_whitespace(token);
if(strcmp(token,"")==0)
{
token = strtok_r(NULL, "\n", &remstr);
continue;
}
}
list1 = g_slist_append(list1, token);
token = strtok_r(NULL,"\n",&remstr);
}
}
int main()
{
int *av,i,j,length;
i=0;
char str[] = " this name of \n the pet is the ffffffffffffffffffffffffffffff\n is \n the \n test\n program";
//GSList *list1 = line_parser(str);
GSList *list1 = NULL;
line_parser(str,list1 );
// printf("The list is now %d items long\n", g_slist_length(list));
length = g_slist_length(list1);
// printf("length=%d", length);
for(j=0;j<length;j++)
{
printf("string = %s\n",(char *)g_slist_nth(list1,j)->data);
}
g_slist_free(list1);
return 0;
}
here I have a list name list1 in the main function, then I passed list1 as an argument to the lineparser() function where the list is changed appending some values. and I want to return the value to the main() function but without using a return statement as I have used the pointer reference while passing argument. but the value is not returned to the main() function. How can I achieve this?
Seems you want to pass the address of the list pointer, and then have the parser update that variable:
void line_parser(char *str,GSList **list1)
{
...
*list1= list;
}
and in main:
main()
{
GSList *list1 = NULL;
line_parser(str, &list1);
...
}
As it appears, g_slist_append() returns the new start pointer of the list. So, essentially, you're trying to change the list1 value from the line_parser() and expecting that value to be reflected back into main().
Well, that is not possible in the current form. C uses pass-by-value for function parameter passing, so all the arguments passed to a function are a separate local copy to the called function, while considering as parameters to the called function.
If you want the change to list1 to be reflected to main(), you need to use a pointer-to-pointer as the input parameter.
Something along the line of
void line_parser(char *str,GSList** list1) { //and other usage
and
line_parser(str,&list1 );
should solve your problem.
There are many ways to do this. One way:
This line GSList *list1 = NULL; creates a pointer, not the GSList structure. You might want to allocate memory for the list using malloc and cast it to a GSList. For example, GSList list1 = (GSList) malloc(sizeof(GSList));
Then in your function line_parser we will need to pass a pointer line_parser(str, &list1)
Remember to free(list1)
Another way would be to create the GSList on the stack. Regardless, we still pass a pointer to line_parser, as mentioned above.
Here is a struct containing the variables
struct theFile{
FILE *fPointer;
char *fileItems[];
int count;
}myFile;
I'm wondering why I get the error invalid conversion from 'char' to 'const char*' when I have my code like this
void saveFile(){
myFile.fPointer = fopen("mileage.txt", "r");
char item;
int i = 0;
while (!feof(myFile.fPointer)){
item = fgetc(myFile.fPointer);
while (item != ',' || item != ' '){
myFile.fileItems[i] = (char*)malloc(sizeof(char));
strcpy(myFile.fileItems[i], item);
i++;
item = fgetc(myFile.fPointer);
}
myFile.count++;
}
}
but I don't have the error when I have item as a pointer
void saveFile(){
myFile.fPointer = fopen("mileage.txt", "r");
char *item;
int i = 0;
while (!feof(myFile.fPointer)){
*item = fgetc(myFile.fPointer);
while (*item != ',' || *item != ' '){
myFile.fileItems[i] = (char*)malloc(sizeof(char));
strcpy(myFile.fileItems[i], item);
i++;
*item = fgetc(myFile.fPointer);
}
myFile.count++;
}
}
Issues that I see:
Issue 1:
struct theFile{
FILE *fPointer;
char *fileItems[];
int count;
}myFile;
is not valid. The flexible array member has to be the last member of the struct. Use
struct theFile{
FILE *fPointer;
int count;
char fileItems[]; // This is an array of char not an array of char*.
}myFile;
instead.
Issue 2:
strcpy(myFile.fileItems[i], item);
is not valid since the second argument is of type char not char*. That's what the compiler is telling you.
Issue 3:
Your code needs to be updated for the flexible way you want to keep adding input data to myFile.
void saveFile()
{
int item;
int i = 0;
myFile.fPointer = fopen("mileage.txt", "r");
// Deal with error condition.
if ( myFile.fPointer == NULL )
{
// Add an appropriate error message.
printf("Unable to open '%s' for reading.\n", "mileage.txt");
return;
}
myFile.fileItems = malloc(i+1);
while ((item = fgetc(myFile.fPointer)) != EOF )
{
if (item != ',' || item != ' ')
{
myFile.fileItems = realloc(myFile.fileItems, i+1);
myFile.fileItems[i] = item;
i++;
}
}
myFile.count = i;
// You need to call fclose(myFile.fPointer) somewhere.
// I am not sure what's the best place in your program to do that.
// This function might as well be that place.
fclose(myFile.fPointer);
myFile.fPointer = NULL;
}
Issue 4:
The name saveFile seems a bit misleading since you are not saving anything to a file. readFile sounds like a better name to me.
In strcpy is a char * argument. In first case you are passing the character variable. So it is not accepting that and throwing the error.
char *strcpy(char *dest, const char *src);
So when you are using the pointer that time it accepting that.
You're confusing single characters with strings. Also, both versions of the code are writing to unallocated memory.
Rather than try to explain this in complete detail, I'm going to suggest you go back to the book(s) you're learning C from, because you've misunderstood some really fundamental things here.
So I have the following question:
I have this struct ListAut
struct ListAut{
char* biggestn;
int sizeof_biggestn;
int total_len;
struct node* avl;
};
Its typedef is as it follows:
typedef struct ListAut *IndexOfAuts;
IndexOfAuts *newIndexOfAuts()
{
int i;
IndexOfAuts *ioa = malloc(27 * sizeof(struct ListAut));
for (i = 0; i < 27; i++)
{
ioa[i]->biggestn = "";
ioa[i]->sizeof_biggestn = 0;
ioa[i]->total_len = 0;
ioa[i]->avl = NULL;
}
return ioa;
}
void insertName(IndexOfAuts * ioa, char *nome)
{
char *aux = malloc(sizeof(nome));
aux = trim(nome);
int index = getIndexOfLetter(aux);
if (nameLen(aux) > getSizeOfLongName(ioa[index]))
{
strcpy(ioa[index]->biggestn, aux);
ioa[index]->sizeof_biggestn = nameLen(aux);
}
ioa[index]->total_len += nameLen(aux);
insert(ioa[index]->avl, aux);
}
This is an important part of a module I need for a project, and on its main it's Seg Faulting. I suspect it's on the creation of an "object" newIndexOfAuts(),
The idea of this module is to have an array of 27 pointers to those structures, one to each letter and another to the special characters;
Now I'm just confused because it might be from the problem above or from a module loader I made:
void loadModules(char *filename, IndexOfAuts * ioa, StatTable st)
{
char *nameofile = malloc(20);
strcpy(nameofile, filename);
FILE *file = fopen(nameofile, "r");
if (file != NULL)
{
int counter, ano;
char *buff, *field, *auxil;
buff = malloc(1024);
field = malloc(200);
auxil = malloc(200);
while (fgets(buff, 1024, file))
{
counter = 0;
field = strtok(buff, ",");
printf("inserting 1st name\n");
insertName(ioa, field);
counter++;
while (!atoi(field))
{
if ((auxil = strtok(NULL, ",")) != NULL)
{
counter++;
field = auxil;
insertName(ioa, field);
}
}
ano = atoi(field);
incPub(st, ano, counter - 1);
}
fclose(file);
}
}
When i run this in main that has the following lines:
printf("Creating Stat Table");
StatTable st=newStatTable();\\This Line is correct, i checked it,i hope
printf("Creating index");
IndexOfAuts* ioa=newIndexOfAuts();
printf("Loading Modules");
loadModules(filename,ioa,st);
Those prints were for me to see where was the cause of the seg fault, but the last line printed was the "Creating Index".
There are several cases of undefined behavior and one memory leak (and a possible case of undefined behavior too):
You have this initialization ioa[i]->biggestn=""; It make the biggestn member point to a constant array of one character (the '\0' character). You then do strcpy(ioa[index]->biggestn,aux); which will write over a constant character, and then go outside of the array writing into unknown memory.
You have this: char* aux=malloc(sizeof(nome)); That allocates only 4 or 8 bytes, which the size of the pointer and not what the pointer points to. Use strlen to get the length of a string.
For the above allocation you also need to allocate a byte extra, as strlen only returns the length of the string without the terminator.
You have aux=trim(nome); This overwrites the pointer you just allocated, leading to a memory leak.
The above call might also lead to undefined behavior if you return a pointer to a local variable or array.
There are probably other problematic lines, these were just the ones I found on a quick glance.
And a general tip: Learn to use a debugger! The debugger is a programmers best tool next to the compiler. If you run your program in a debugger, the debugger will stop at the location of the crash, and let you examine (and also walk up) the function call stack, as well as let you examine values of variables.
I've got a linked list of nodes that contain a string of characters. The program reads characters from stdin until it reaches a new line and once it has it puts this string of characters into the a new node of the list.
I've done some debugging of the different steps involved in the program and can see the list of nodes being created correctly.
However, the printf statement doesn't seem to do anything if I'm stepping through the code. If I don't step through and just run the code through I get:
Cannot access memory at address 0x2e666564
Cannot access memory at address 0x2e666564
Cannot access memory at address 0x2e666564
My source code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
char *string;
struct Node *next;
} List;
List *addNode(List *currentList, char *character)
{
List *tempList = calloc(1, sizeof(List));
tempList->string = strdup(character);
tempList->next = currentList;
return tempList;
}
void printList(List *currentList)
{
while (currentList != NULL)
{
printf("%s", currentList->string);
currentList = currentList->next;
}
}
int main ()
{
char currentCharacter;
char *currentString;
List *mainList = NULL;
do
{
currentCharacter = getchar();
if (currentCharacter == '\n')
{
mainList = addNode(mainList, currentString);
currentString[0] = '\0';
} else {
strcat(currentString, ¤tCharacter);
}
} while (currentCharacter != '.');
mainList = addNode(mainList, currentString);
printList(mainList);
return 0;
}
You're calling strcat on an invalid pointer.
Something like this would work:
char currentString[128];
currentString[0] = '\0';
currentCharacter isn't null-terminated and so strcat won't work. Use strncat instead.
Several problems here.
The main problem is that you have not allocated space for your currentString. strcat requires that there be space in the destination array (currentString).
Also problematic: when the user enters '\n', you haven't null terminated the string you are appending, so strdup will not quite work.
Your main function never initializes currentString to point to allocated memory, so your call to strcat just starts adding characters to whatever '\0'-terminated string currentString happens to be pointing to.
You don't need strcat. You do need to assign currentString at some point. Replace:
#define BUFFER_SIZE 128
/*
shouldn't need more than 128 characters for a line of console
but you can expand it later if you want
*/
int main() {
List *mainList = NULL;
char *buffer = malloc(sizeof(char)*BUFFER_SIZE);
int currentIndex = 0;
char currentCharacter;
do {
currentCharacter = getChar();
if (currentCharacter == '\n' || currentIndex == (BUFFER_SIZE-1))
buffer[currentIndex] = 0; //the null byte needs to be added before strdup is called
mainList = addNode(mainList, buffer);
currentIndex = 0;
} else {
buffer[currentIndex++] = currentCharacter;
}
} while (currentCharacter != '.');
mainList = addNode(mainList, buffer);
return 0;
}