I'm trying to create a linked list structure to store data. The head of the linked list seems to be updating somehow. I have the following code. I can't seem to figure out how put char array data into a node and keep it from updating when the address to said char array's data updates.
The following code prints out whatever string is passed into the processStr function. How do I keep head from updating ?
//Linked List Structure
mainNode *head = NULL;
//take and store word in data structure
void processStr(char *str){
//char array
char strArray[sizeof(str)+1];
//stores lower case string
char strLower[strlen(str)];
int i;
for(i = 0; str[i]; i++)
strLower[i] = tolower(str[i]);
strLower[i] = '\0';
//printf("%s : ", strLower);
//Starts Linked List
if(head == NULL){
mainNode *mainPtr = (mainNode *)malloc(sizeof(mainNode));
nameNode *namePtr = (nameNode *)malloc(sizeof(nameNode));
mainPtr->name = strLower;
mainPtr->numOccurances = 1;
mainPtr->next = NULL;
mainPtr->nextName = namePtr;
namePtr->name = strArray;
namePtr->next = NULL;
head = mainPtr;
}
printf("%s : " , head->name);
}
You assign the pointers mainPtr->name and namePtr->name to variables strLower and strArray that are declared locally in processStr(). That means after that function returns, any access to these pointers results in undefined behaviour. You could do sth. like
mainPtr->name = strdup( strLower );
instead to allocate memory for the strings.
Btw.: strLower must also be declared as char strLower[strlen(str)+1];
The above code will only run once only which will add information to head only once. If you want to add more information in case of second run then add code for else condition. Example:-
if ( head == NULL ) {
// code to insert data in case of first run
}else{
// code to insert data for second run and so.....
}
Related
I'm trying to create an alphabetically ordered linked list from a file by placing the node in the correct spot after reading it. The file must not be alphabetically ordered. The program reads the file correctly and I'm able to add everything at the end of the list.
Place search_place(Place first, char *new){
Place aux = first;
while (aux->abcnext != NULL){
if ( strcmp(new,aux->place) > 0)
aux = aux->abcnext;
else
break;
}
return aux;
}
void insert_place(Place first, char* string){
Place previous,temp,new;
previous = search_place(first, string);
if (previous->abcnext == NULL){
new = create_place();
previous->place = string;
new->abcnext = previous->abcnext;
previous->abcnext = new;
}
else{
new = (Place)malloc(sizeof(place_node));
new->place = string;
new->abcnext = previous;
previous = new;
}
}
Place create_place(){
Place aux;
aux=(Place)malloc(sizeof(place_node));
if (aux!=NULL){
aux->place=malloc(25*sizeof(char));
aux->abcnext=NULL;
}
return aux;
}
typedef struct placenode*Place;
typedef struct placenode{
char *place;
Place abcnext;
}place_node;
Considering the results that I've obtained from this code I suppose the problem is related to either pointers or the header of the linked list or both. With 4 places: P, Z, W, L - I get only P -> Z from the list.
if (previous->abcnext == NULL){
new = create_place();
previous->place = string;
new->abcnext = previous->abcnext;
previous->abcnext = new;
}
A couple of obvious problems with the above code. Firstly, you don't set new->place - you replace previous->place which doesn't seem right. So your new node will have NULL for it's "place" and you'll have lost the value for the previous node.
Secondly you're assigning the value of string rather than making a new copy. If you're using the same string each time you call the function, you'd end up with all the nodes pointing to the same string.
You should do something like
new->place = malloc(strlen(string)+1);
strcpy(new->place, string);
or if your version of C has it, use strdup
new->place = strdup(string);
(to preface this my C is terrible)
I'm trying to send a string from iOS to a BLE device. I encode the string in swift and write it like this:
func sendUserName(userName: String) {
let bytes: [UInt8] = Array(userName.utf8)
print(bytes.count)
let data = NSData(bytes: bytes, length: bytes.count)
capsenseLedBoard!.writeValue(data, forCharacteristic: userIdCharacteristic, type: CBCharacteristicWriteType.WithResponse)
}
I send in this string "THISISATEST123456789" and this line print(bytes.count) prints out 20.
I recieve the data on the BLE device like this and pass it to the below userDidConnect function:
userDidConnect((char *)wrReqParam->handleValPair.value.val);
I have a struct called Event that looks like this:
struct Event {
char time[20]; // The time in ISO 1601 format
char name[3]; // The two character name of the event. See header for declarations.
char userId[20]; // The userId of the connected user if one is present.
struct Event* next;
};
I have a global variable declared like this:
char currentlyConnectedUserID[20];
I then have an enqueue function that looks like this:
/**
Creates a new Event and adds to the linked list.
#param time The time in ISO 8601 format.
#param name The name descriptor of the event ("VS", "VO", etc.)
#param userId The id of the user who is currently connect (if they are connected).
*/
void enqueueEvent(char time[20], char name[3], char userId[20]) {
struct Event* temp = (struct Event*)malloc(sizeof(struct Event));
strncpy( temp->time, time, 20);
strncpy( temp->name, name, 3);
strncpy( temp->userId, userId, 20);
temp->next = NULL;
if(front == NULL && rear == NULL) {
front = rear = temp;
return;
}
rear->next = temp;
rear = temp;
}
I have a function that accepts a new userId and then creates a new Event off of it and adds it to the linked list..well this is what it's suppose to do:
void userDidConnect(char *userId)
{
size_t destination_size = sizeof(userId);
snprintf(currentlyConnectedUserID, destination_size, "%s", userId);
//enqueueEvent("2007-03-01T13:00:20", "UC", currentlyConnectedUserID);
showMessageInUART(currentlyConnectedUserID, sizeof(currentlyConnectedUserID));
}
Currently if I run the userDidConnect method above I'm able to printout the currentlyConnectedUserID properly. However, if I uncomment out this line:
//enqueueEvent("2007-03-01T13:00:20", "UC", currentlyConnectedUserID);
I get a "crash". I'm doing this in a fairly obscure IDE (PSoC Creator from Cypress) so I don't see any error logs or IDE crash logs. The only way I can tell is that the showMessageInUART is never called, so I know it has to be that line.
I'm able to successfully create and enqueue a new Event if I do this:
enqueueEvent("2007-03-01T13:00:20", "UC", "1234567891234567891");
My only thought is that maybe the size of the array is wrong? Maybe? Or perhaps there is some trailing \0 that is screwing things up?
Suggestion updates:
I've tried doing this:
size_t destination_size = strlen(userId) + 1;
Which gives the correct value into currentlyConnectedUserID however enqueueing still causes a crash.
--
I've replaced strcpy with strncpy which is still causing a crash ;(
--
Tried this to ensure I didn't overflow which still didn't work:
sprintf(currentlyConnectedUserID, "%.19s", userId);
UPDATE
I updated my enqueue to look like this since don't have breakpoints:
void enqueueEvent(char time[20], char name[3], char userId[20]) {
UART_UartPutString("start enqueue");
struct Event* temp = (struct Event*)malloc(sizeof(struct Event));
UART_UartPutString("1");
strncpy( temp->time, time, 20);
UART_UartPutString("2");
strncpy( temp->name, name, 3);
UART_UartPutString("3");
strncpy( temp->userId, userId, 20);
UART_UartPutString("4");
temp->next = NULL;
UART_UartPutString("5");
if(front == NULL && rear == NULL) {
front = rear = temp;
return;
}
rear->next = temp;
rear = temp;
}
This line is crashing:
strncpy( temp->time, time, 20);
aka we never make it here: UART_UartPutString("2");
If I call this same function from main it works fine. Any idea why it would be crashing here when called from a different method?
The strcpy funtion Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).
Therefore, I propose you to change the enqueueEvent funtion, using strncpy instead of dangerous strcpy as :
void enqueueEvent(char time[20], char name[3], char userId[20]) {
struct Event* temp = (struct Event*)malloc(sizeof(struct Event));
strncpy( temp->time, time,20);
strncpy( temp->name, name,3);
strncpy( temp->userId, userId,20);
temp->next = NULL;
if(front == NULL && rear == NULL) {
front = rear = temp;
return;
}
rear->next = temp;
rear = temp;
}
Change also the allocation of temp pointer from local stack of the enqueueEvent function to global level because the pointer allocation is vanished when going outside of the function.
I have been building this hash table function that is given an array it gets a word from and a pointer to an array that it fills with my linked list struct. It compiles correctly but I get a segmentation fault at - *hashTable[hashVal] = *newNode; .
void hashTableCreate(char *array, list *hashTable[]) {
while(arrayPos < getArrayLength(array)) {
char *temp = getWord(array);
int hashVal = hashingFunc(temp);
if((*hashTable[hashVal]).word == temp ) {
(*hashTable[hashVal]).count = (*hashTable[hashVal]).count+1;
}
else {
list *newNode = malloc(sizeof(list));
strcpy(newNode->word,temp);
newNode->count = 1;
*hashTable[hashVal] = *newNode;
}
}
}
It's called like this:
void timeStructures(char *newArray) {
list *hashTable[3000];
hashTableCreate(newArray, hashTable);
}
I know this is to do with the way I am using my pointers but I can't figure it out. Any help would be appreciated.
There are several problems on this code:
You seem you are using extra asterisks when assigning newNode to hashTable.
You can use ++ operator to increment count, and use -> to access a member of a pointer to struct.
getWord is unknown to me, but seems impossible it can return a pointer to a string contained inside an element of hashTable, which means the next if will always be false (newNode's word is a copied string, not a pointer to array's word), as it compares memory addresses instead of strings.
You never free temp neither hashTable elements, which seems another misconception of what you are doing here.
As noted by #kaylum , you should initialize hashTable so you avoid comparing against unassigned array elements, neither modifying count on them.
hashTable has to be passed as a pointer to hashTableCreate, or this will work on a copied version of it:
Try this:
void hashTableCreate(char *array, list *(*hashTable[])) {
while(arrayPos < getArrayLength(array)) {
char *temp = getWord(array);
int hashVal = hashingFunc(temp);
if((*hashTable)[hashVal] != NULL &&
strcmp((*hashTable)[hashVal]->word, temp) == 0 ) {
(*hashTable)[hashVal]->count++;
}
else {
list *newNode = malloc(sizeof(list));
strcpy(newNode->word,temp);
newNode->count = 1;
(*hashTable)[hashVal] = newNode;
}
free(temp);
}
}
void timeStructures(char *newArray) {
list *hashTable[3000];
int i;
// Initialize hashTable pointers to NULL
for(i = 0; i < 3000; i++) {
hashTable[i] = NULL;
}
hashTableCreate(newArray, &hashTable);
// Free hashTable elements, malloc'ed at hashTableCreate
for(i = 0; i < 3000; i++) {
if(hashTable[i] != NULL) {
free(hashTable[i]);
}
}
}
Note 1: you never check if hashVal is higher than 3000, which might be fine if you know what you are doing, aka, you know hashingFunc will never return 3000 or higher. If you do not, you'll need to care about growing hashTable appropriately.
Note 2: executing getArrayLength on each loop might be a performance problem for large lists. You probably prefer to create a variable to contain its value and execute it only once.
Note 3: It might be some easier if you declare hashTable as a plain list of elements, not a list of pointers to elements, like list hashTable[3000];, but I don't know exactly what you're looking for. Also, it will always waste 3000 list elements of memory, so might be a performance problem.
im trying to insert one list in the end of another
with this code:
typedef struct Element
{
int vKey;
char vInfo[30];
struct Element *pNext;
} tsElement;
typedef struct
{
tsElemento *pFirst;
int vLength;
} tsLDSE;
void Unir(tsLDSE *pListIn, tsLDSE *pListOut)
{
tsElement *pElementOut;
pElementOut = pListOut->pFirst;
while (pElementOut != NULL)
{
pElementOut = pElemenoOut->pNext;
}
pElementOut = pListIn->pFirst;
pListOut->vLength = pListOut->vLength + pListIn->vLength ;
}
i checked printing the adresses, pElementoOut is really the end of the first list and is poiting to NULL, then it receives the fisrt adress of the second list, but when i print it out it only prints the first list and i can't figure out why.
Your function Unir only adds the length of the input list to the length of the output list.
This loop:
while (pElementOut != NULL)
{
pElementOut = pElemenoOut->pNext;
}
Only gets pElementOut to be NULL.
In addition, when you write pElementOut = pListIn->pFirst;, all you change is the local variable pElementOut.
What you want to do instead is this:
while (pElementOut->pNext != NULL)
{
pElementOut = pElementOut->pNext;
}
pElementOut->pNext = pListIn->pFirst;
This puts the first element of pListIn at the end of the last element of pListOut.
Also, add a NULL check at the beginning of your function! You can easily get a NULL pointer dereference there if you aren't careful.
I don't know why I can read the Linked list without problems in LABEL : 1 ; but the program just crashes and print grabage in the LABEL : 0 ;
In other terms, why the linked list works fine inside the lecture function , but not outside it ?
Here is my code :
/* including libraries */
#define V 20
typedef struct DATA{
char* NomP;char* NomA;
struct DATA *Next;
}DATA;
// Prototypes .
int main(void)
{
char FileName[V];
puts("Data file ? : ");gets(FileName);
FILE* fs = fopen(FileName,"r"); // Check if fs is NULL
DATA *HEAD = MALLOC(sizeof (DATA)); int len = lecture_data(fs,HEAD);
print_data(HEAD,len); //LABEL : 0
return 0;
}
int lecture_data(FILE *fs,DATA *ROOT)
{
char cNom[V],cArticle[V];
int eofs=0;int i=0;
while(!eofs)
{
DATA *Data = MALLOC(sizeof (DATA));
fscanf(fs,"%s %s",cNom,cArticle);
Data->NomA = MALLOC(strlen(cArticle)+1);
Data->NomP = MALLOC(strlen(cNom)+1);
strcpy(Data->NomA,cArticle);
strcpy(Data->NomP,cNom);
if( i==0 )
{
Data -> Next = NULL ;
ROOT = Data ;
}
else
{
DATA* Ptr = ROOT ;
while( (Ptr->Next) != NULL )
{
Ptr = (Ptr -> Next);
}
Data -> Next = NULL ;
Ptr -> Next = Data ;
}
i++;
eofs = feof(fs) ;
// check ferror(fs) here
}
puts("Start of reading :");
print_data(ROOT,len); // LABEL : 1
puts("End Of Reading ");
fclose(fs);
return i;
}
Here is the printing function :
void print_data(DATA *L_ROOT,int len)
{
int i = 0 ;
DATA* LINK;
LINK = L_ROOT;
while( LINK != NULL )
{
printf("%d : DATA->NomA : %s\n",i,LINK->NomA);
printf("%d : DATA->NomP : %s\n",i,LINK->NomP);
LINK = LINK -> Next ;
i++;
}
}
You're allocating data for the root of the list in the main function, and pass that to the function so that it may populate the list, but the first time you allocate an element you overwrite the ROOT pointer value.
this makes you lose the only connection between the function and the outside world (since the return value is just a number), so the HEAD value in main() is left pointing at nothing meaningful (because your function never uses it), while the list remains allocated in some memory location that no one outside is pointing to, which means it's lost. Running valgrind would have been able to identify this.
You can fix that by changing the (i==0) case from -
ROOT = Data ;
into
ROOT->next = Data ;
but make sure you're ignoring the data of the root node later on.
p.s. - using capitalized variables and types is not considered a good idea (it's mostly reserved for macros). It also makes your code look like you're shouting :)
The (main) problem is that lecture_data doesn't use it's input parameter (ROOT) for storage of the linked list, nor does it return the internal generated list. The correct way to handle this is to have ROOT reference the calling scope's parameter so that it can update it's reference as necessary.
int main(void)
{
char FileName[V];
puts("Data file ? : ");gets(FileName);
FILE* fs = fopen(FileName,"r"); // Check if fs is NULL
DATA *HEAD = NULL;
int len = lecture_data(fs, &HEAD);
print_data(HEAD); //LABEL : 0
return 0;
}
int lecture_data(FILE *fs,DATA **ROOT)
{
char cNom[V],cArticle[V];
int i=0;
DATA *current = *ROOT; // grab the passed in reference
while(!feof(fs))
{
if(fscanf(fs,"%s %s",cNom,cArticle) <= 0) // This call is only successful if the return value is > 0
{
// check ferror(fs) here
continue; // Can also "break;" here, essentially, it's eof already
}
DATA *Data = MALLOC(sizeof (DATA));
Data->NomA = MALLOC(strlen(cArticle)+1);
Data->NomP = MALLOC(strlen(cNom)+1);
strcpy(Data->NomA,cArticle);
strcpy(Data->NomP,cNom);
if(NULL == current) // ROOT was uninitialized before the call
{
Data -> Next = NULL;
*ROOT = Data;
}
else
{ // We don't need to iterate the list in every step.
Data->Next = current->Next; // This part allows the function to insert nodes in the middle / end of an existing list
current->Next = Data;
current = Data;
}
i++;
}
puts("Start of reading :");
print_data(ROOT); // LABEL : 1
puts("End Of Reading ");
fclose(fs);
return i;
}
Note: print_data didn't do anything with the len parameter, so no need passing it in at all.
This solution is not wasteful in terms of "empty" nodes in the list (as opposed to having an empty head to ignore), and is suitable both for initializing the list from scratch AND for cases where you need to append / insert into an existing list.