(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.
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);
This might be a bad question but I'm completly lost. I have this code:
struct nodoTemas* search_in_list(char * val, struct nodoTemas **prev,struct nodoTemas *head/*, struct nodoTemas *curr*/)
{
struct nodoTemas *ptr = head;
struct nodoTemas *tmp = NULL;
bool found = false;
printf("\n Searching the list for value [%s] \n",val);
while(ptr != NULL)
{
if(ptr->nombreTema == val)
{
found = true;
break;
}
else
{
tmp = ptr;
ptr = ptr->next;
}
}
if(true == found)
{
if(prev)
*prev = tmp;
return ptr;
}
else
{
return NULL;//si no ha encontrado nada devuelve NULL
}
}
And I test it, in a specific file to test it, like this:
char * var="tema1";
char * var2="tema2";
head=add_to_list(var,true,head,curr);
curr=head;
curr=add_to_list(var2,true,head,curr);
struct nodoTemas* nodoBuscado;
char *temaABuscar="tema4";
nodoBuscado=search_in_list(temaABuscar, NULL,head);
if(nodoBuscado!=NULL)
printf("VALOR DEL NODO %s\n",nodoBuscado->nombreTema);
And it works perfectly fine no matter what I do. If I look for something that exists it prints it and so on. Now on my main file I get the char * my server gets the char * from a message. I thought this failed so I tried several things, this being one of them:
printf("MATCH %d \n" , strcmp(temaRecibido,head->nombreTema));
And I get a 0 as a result. So the strings are the same. But the search fails, in this other file. I've printed it, I've checked for their strlen sizes, and it all matches.
So I believe I'm looking at the wrong side but I cannot understand why code that is working in one place does not work in other. Should I look for the mistake somewhere else? Also, if I do strlen of a string WITH null and one without null, are they the same size? man says it excludes the terminating byte but I am unsure about this.
I'm sorry if the post is lacking I wasn't sure how to properly present it.
You cannot compare strings like
if(ptr->nombreTema == val)
You should use strcmp
if(strcmp(ptr->nombreTema, val) == 0)
im not sure if you can compare strings in C that way...
if you search for the string "tema1" instead a pointer to "tema1" what is the result?
also, check this http://www.wikihow.com/Compare-Two-Strings-in-C-Programming.
First post, extremely limited in coding knowledge and new to C. Be gentle! I am at the point where "trying" different things is just confusing me more and more. I need someone's correct guidance!
This particular problem is from an online edX course I am attempting which ultimately when implemented correctly, checks a given word read in from a text file (the 'check' function) and compares it to each word read into (from the 'load' function) a linked list of structs.
I believe I have the load function implemented correctly as when I use gdb, as I am seeing what I anticipate as I step through it, but my question and my problem relates specifically to the check function. I still have a lot to implement to finish my code but while testing with gdb, I am not seeing values of the char* member of the struct correspond with what I anticipate I should see.
When using gdb and stepping through the 'check' function and trying to access the dword member of the struct nodes in the linked list I created in the load function, I anticipate I should see a string for the char* member. For instance, I anticipate the word "cat" assigned to current->dword , but am instead seeing in gdb when I test:
~(gdb) print current->dword
$13 = 0xbfffede2 "\004\b\214\365\372D\300\355\377\277"
My thoughts are that I'm still only accessing an address somehow and not the actual value, but I'm oblivious as to why this is. When the node is created in the load function, a value is assigned to the dword member correctly (at least as far as I can tell while stepping through the code in gdb) but doesn't seem to be accessed correctly in the check function. Any help for a newbie would be appreciated!
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dictionary.h"
typedef struct node
{
char* dword;
struct node* next;
}
node;
// keep track of #of words in dictionary loaded
int wordCounter = 0;
// create root for hash table
node* root[26];
// create cursor to keep place in creating, pointing, and traversing through nodes
node* current = NULL;
/**
* Returns true if word is in dictionary else false.
*/
bool check(const char* word)
{
// size of word read into buffer
int wordSize = sizeof(word);
// prepare to make a new lowercase only word for comparison to lowercase only dictionary
char bufWord[wordSize];
// make it
for(int i = 0; i < wordSize; i++)
{
if (i == wordSize - 1)
{
bufWord[i] = '\0';
}
else
{
bufWord[i] = tolower(word[i]);
}
}
// hash word to achieve proper root node location
int hash = bufWord[0] - 97;
// point to the correct root node to begin traversing
current = root[hash];
// make sure there is even a word in hash table location
if(root[hash] == NULL)
{
return false;
}
else if(root[hash] != NULL)
{
// progress through the nodes until the last node's next pointer member is NULL
while(current != NULL)
{
// compare 1st letter only of current->dword[i] to bufWord[i] to save time
// if they don't match, return false
// if they do match then continue
\
char dictWord[wordSize];
// hold copy of struct member value to compare to dictWord
char* wordTemp = current->dword;
//
for(int i = 0; i < wordSize; i++)
{
dictWord[i] = wordTemp[i];
}
// do a spell check
if(strcmp(bufWord, dictWord) == 0)
{
return true;
}
else
{
// set current to the next node if any or NULL if it's already the last node in the list
current = current->next;
}
}
}
return false;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
// buffer for reading in dictionary words
char wordIn[LENGTH + 1];
// open the dictionary file
FILE* newDict = fopen(dictionary, "r");
for (int i = 0; i < 27; i++)
{
root[i] = NULL;
}
// while there are words to read
while(fscanf(newDict, "%s ", wordIn) > 0)
{
// keep track of #of words for constant time read in size function
wordCounter++;
// hash the first letter for the location in root
int hash = wordIn[0] - 97;
// malloc space for a new node
node* newNode = malloc(sizeof(node));
// error check
if (newNode == NULL)
{
return false;
}
// set value member of node to current word
newNode->dword = wordIn;
// first insertion into linked list if that root node has not been used yet
if(root[hash] == NULL)
{
// sets to NULL
newNode->next = root[hash];
// link it
root[hash] = newNode;
}
else if(root[hash] != NULL)
{
// starts at the root
node* current = root[hash];
// insert into new beginning of list
newNode->next = current;
root[hash] = newNode;
}
}
fclose(newDict);
return true;
}
/**
* Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int size(void)
{
return wordCounter;
}
/**
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool unload(void)
{
// TODO
return false;
}
The source of your problem is the line:
newNode->dword = wordIn;
wordIn is a local array in load. You are storing the address of wordIn in the dword of your nodes. When you return from load, those addresses are no valid any longer.
What you need to do is allocate memory for the string in wordIn, assign the allocated memory to newNode->dword and copy the contents of wordIn to newNode->dword.
If your platform provides the non-standard function strdup, you can change the above line to:
newNode->dword = strdup(wordIn);
If not, it is easily implemented:
char* strdup(char const* in)
{
char* r = malloc(strlen(in)+1);
strcpy(r, in);
return r;
}
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.....
}
I have a linked list whose elements are of type
typedef struct List * News;
struct List
{
char * Text;
News NextN;
};
In the main function I declared an array of type News as follows
News PTH[50];
for (i = 0; i < 50; i++)
{
PTH[i] = (News) malloc(sizeof(struct List));
PTH[i] -> Text = NULL;
PTH[i] -> NextN = NULL;
}
I added new nodes in the beginning of the list with
if ( PTH[i] -> Text == NULL)
PTH[i] -> Text = msg;
else
{
t -> Text = msg;
t -> NextN = PTH[i];
PTH[i] = t;
}
Where msg is a array of char of length 2000; and and then tried to print the texts apointed by PTH[i] -> Text with
p = PTH[i];
if (p -> Text != NULL)
{
printf("%s", p -> Text);
p = p -> NextN;
}
while (p != NULL)
{
printf("%s", p -> Text);
p = p -> NextN;
}
}
This algorithm only add one node. The error is how I define the PTH or is there an error in how I put nodes in the list.
maybe it is something like this you are after:
if ( PTH[i]->Text == NULL )
{
PTH[i]->Text = msg;
}
else // first create node, then append by first finding the last node
{
News it = NULL;
News t = malloc( sizeof(struct List));
t->Text = msg;
t->NextN = NULL;
for ( it = PTH[i]->NextN; it != NULL; it = it->NextN)
{
;
}
it->NextN = t;
}
Assuming that msg is a buffer you use to receive new data, you have to be careful with this statement:
PTH[i] -> Text = msg;
Since msg is a pointer to char, the assignment will not copy the characters sequence; instead, it will just make PTH[i]->Text point to the same location as msg. This is problematic if you change the contents in msg - the changes are, of course, reflected back in every PTH[i]->Text for which the assignment was made, namely, every node that you ever added. Probably, not quite what you want. This is why it seems like you can only handle one node at a time. They all get the same text, because they all point to the same memory location.
You should use strcpy instead:
strcpy(PTH[i]->Text, msg);
Don't forget to include string.h.
This assumes that PTH[i]->Text is already allocated. You might want to use strncpy if there is a chance that msg exceeds 2000 characters, to avoid buffer overflows.
If you didn't alloc space for PTH[i]->Text, you could allocate exactly strlen(msg)+1 positions for PTH[i]->Text and then use strcpy safely. Or you could use strdup, also declared in string.h, which has exactly this behavior:
PTH[i]->Text = strdup(msg);