How to fix a condition error from a string array - c

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.

Related

How can I convert char* to char[] in C and then add it in an array without problem?

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];
}

How can I move to the next array element?

I'm trying to assign a number in an array one by one. If the pointer is pointing at the first element of the array, then it means that the array is empty and it will be assigned with a number. But for some reason, it doesn't seem to move the pointer to the next element. How can I fix this?
unsigned char number= '1'; //random number
unsigned char array[8];
int count = 0;
unsigned char *ptr;
int main(){
while(count < 5){
reserve();
count ++;
ptr++; //move to next element
}
}
void reserve(void){
if(ptr = array){ //if pointer is at the first element of the
*ptr = number; //array then it means it's empty
}
else{ //not empty array
*ptr = number;
}
}
EDIT:
if(ptr = array) was a typo. The problem was not assigning the initial value for *ptr. I have a new question, though. Someone who commented below said not to use global variables. I had thought about using static unsigned char *ptr = array in the reserve function, but that would reset to the initial assignment when it is called again. What did that person mean by using explicit dependencies?
Edit: The first paragraph is incorrect. See Oka's comment.
You are initialising a pointer but it doesn't point to anything. This is considered dangerous because when you use it, it just points to a random (not actually random but may as well be) memory address.
You could use (array + count) to step through the array (best not to step array itself as then you run the risk of forgetting and losing the address to the array creating a memory leak).
Also as some comments have pointer out you need to use == for comparison.
int main(){
uint number = 1;
unsigned char array[8];
// a for loop is a good way to have a loop that ends when a condition is met with an incrementing variable
for (int count = 0; count < 4; count++){
reserve(array+count);
}
}
void reserve(char * ptr){
if(ptr == array){ //if pointer is at the first element of the
*ptr = number; //array then it means it's empty
}
else{ //not empty array
//do someting else? Or just set them all equal to number
}
}

Need to change "a" to "e" or "o" depending if "a" position is even or odd using pointers

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.

Uint8_t Setting Itself

I have something of a minor annoyance rather than a bug but I can't figure out why it's occurring. I have an array index and 2D gchar array declared like this:
gchar FilterArray[10][51];
static uint8_t ArrayIndex = 0;
static gchar ScanLine[9640];
Now, the first time I use Array Index it's somehow the value 115. I didn't set it anywhere in the code before using it. If I only print it out after I use it in the strcpy command, its' value is 115. If I print it out before the strcpy command, it's value is correct for the duration of the program.
while(FilterAmount != 0)
{
g_io_channel_read_chars (source,(gchar *) ScanLine,1,&BytesRead,&GlibError);
if(ScanLine[0] == FilterTerminator[0]) {
printf("Array Index: %i\n", ArrayIndex);
if(strlen(FilterName) > 0){
printf("Array Index: %i\n", ArrayIndex); //if I only print before, value is correct
strcpy(FilterArray[ArrayIndex],FilterName);
printf("Array Index: %i\n", ArrayIndex); //if I only print after, value is incorrect
ArrayIndex++;
FilterAmount--;
FilterName[0] = '\0';
}
}
else {
strcat(FilterName, ScanLine);
}
}
Presumably, FilterName is excessively long and strcpy(FilterArray[ArrayIndex],FilterName) writes beyond the end of FilterArray and over ArrayIndex. That ArrayIndex seems correct if printed before the strcpy might be because the value is kept in a register and not loaded again from the overwritten memory location.

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.

Resources