I have one long array, and I'm trying to figure out how to split it up into two separate arrays, the second array has the right contents but the first is empty, I'm also getting an Abort Trap:6 and I'm not sure what that means.
I have an array called entireA, which looks something like this:
HELLO:WORLD, I want to put HELLO in a separate array (firstA) and WORLD in secondA. When I print first and second array at the end, secondA has the right contents but firstA doesn't event though I'm printing to check if the right characters are being passed over and they are -- but the firstA is still empty and I'm getting and abort trap i don't understand.
I've just started learning C, why is the first array empty and what does the error mean?
#define ARRSIZE 10000
char entireA[ARRSIZE] = "";
char firstA[ARRSIZE] = "";
char secondA[ARRSIZE] = "";
strcpy(entireA,"HELLO:WORLD\n");
int firstVar = 0;
int entireVar = 0;
while(entireA[entireVar] != ':') {
if(entireA[entireVar] == ';') {
break;
}
printf("%c \n",entireA[entireVar]);
firstA[firstVar] = entireA[entireVar];
firstVar++;
entireVar++;
}
firstA[firstVar] = '\0';
int secondVar = 0;
entireVar++; //skip ':'
while(entireA[entireVar] != '\n') {
secondA[secondVar] = entireA[entireVar];
secondVar++;
entireVar++;
}
secondA[secondVar] = '\0';
printf("%s", firstA);
printf("%s", secondA);
There is nothing wrong with the code you posted.
After execution, the variables have the following values:
entireA 0x02efcdb4 "HELLO:WORLD\n" char[0x00002710]
entireVar 0x0000000b int
firstA 0x02efa69c "HELLO" char[0x00002710]
firstVar 0x00000005 int
secondA 0x02ef7f84 "WORLD" char[0x00002710]
secondVar 0x00000005 int
Whatever your problem is, it's most likely something to do with your environment. I would suggest reducing the value of ARRSIZE to, say 80 characters, and seeing if that changes your results.
Related
I am trying to create a formatted string , however I do not know why I cannot print global array which I have modified inside the function.Also the strange behavior is that I cannot access only a specific global array (rand_session_key) rest of the other global arrays are behaving as normal(similar operations are being done on them except their size varies) and I can access their value properly. This code is run on an esp32 (DOIT Dev Kit V1) (with Arduino-Core) , when I run this program on my computer (modifying a few functions etc.) the result is what I expect , I think I am overlapping the characters in the memory or accessing it the wrong way , but had it been the case I would not have yielded the expected output on my computer.
I tried to modify my program and made it more verbose. Also I ran the same code (with some obvious modifications to make it run on my computer) , and the result is good as expected.
char persistent_peripheral_id[] = "FRUCTOSE96";
char rand_session_iden[7] = {'\0'};
char rand_session_key[17] = {'\0'};
char rand_session_channel[3] = {'\0'};
char *generate_random_session_identifier(char *rand_session_iden_local)
{
srand(time(NULL));
int counter = 0;
for (counter = 0; counter < 6; counter++)
*(rand_session_iden_local + counter) = (random(10) % ('~' - ' ')) + 'k';
rand_session_iden_local[counter] = '\0';
printf("Identifier : %s\n", rand_session_iden); //acessing global defintion of array everything is good until here
return &rand_session_iden_local[0];
}
char *generate_random_session_key(char *rand_session_key_local)
{
srand(time(NULL));
int counter = 0;
for (counter = 0; counter < 16; counter++)
*(rand_session_key_local + counter) = (random(10) % ('~' - ' ')) + 'b';
rand_session_key_local[counter] = '\0';
printf("Key : %s\n", rand_session_key);//acessing global defintion of array everything is good until here
return &rand_session_key_local[0];
}
char *generate_random_session_channel(char *rand_session_channel_local)
{
srand(time(NULL));
int channel_value = random(100);
sprintf(rand_session_channel_local, "%03ld", channel_value);
printf("Channel : %s\n", rand_session_channel);//acessing global defintion of array everything is good until here
return &rand_session_channel_local[0];
}
void begin_exchange_package()
{
//If this does not works here (observe rand_session_key) , it will not work for sprintf also ??
printf("\n %s-%s-%s-%s \n", (char *)persistent_peripheral_id,
generate_random_session_identifier(rand_session_iden),
generate_random_session_key(rand_session_key),
generate_random_session_channel(rand_session_channel));
//Notice it prints here ????
printf("\n %s \n",generate_random_session_key(rand_session_key));
Serial.println("Done");
//sprintf((char *)plain_text_package, "{\"p\":\"%s\",\"r\":\"%s\",\"k\":\"%s\",\"c\":\"%s\"}", (char *)persistent_peripheral_id,(char *)rand_session_iden, (char *)rand_session_key , (char *)rand_session_channel);
}
void setup()
{
Serial.begin(115200);
begin_exchange_package();
}
void loop()
{
}
The Output is
FRUCTOSE96-tnltkp--094
Where I expected all the 4 arrays to be printed ?? but it does print separately , is my array being terminated in the wrong way ?? also the logic to assign a random character will always yield a printable ASCII Character (I learned this from a forum on esp32's website)
This code ...
sprintf(rand_session_channel_local, "%03ld", channel_value);
... requires rand_session_channel_local to point to an array of at least four characters, because at will print at least three digits plus a string terminator. The array into which it points, rand_session_channel, is only three characters long. The resulting behavior is undefined.
The observed manifestation of the UB is consistent with the global arrays being laid out in memory such that rand_session_key immediately follows rand_session_channel, such that overflowing the latter means that the string terminator is written to position 0 of the former, making it an empty string. Note, however, that you cannot rely on predicting manifestations of UB, nor is it generally of much use to analyze them. Instead, avoid exercising UB.
It's unclear what random function you are using, since the C standard library's does not take an argument, but if the argument to yours specifies an exclusive upper bound then you could just change the sprintf format to "%02ld". Alternatively, increase the size of rand_session_channel to at least 4.
So I've got this here:
#include <stdio.h>
char halloString[] = "Ha::ll::o";
char perfumeString[] = "47::11";
char veryLongString[] = "47::11::GHesd::dghsr::bfdr:hfgd46dG";
char *extract (char *input) {somethinghappenshere}
where extract needs to get all characters after the last double ":" of given input:
"o" for halloString
"11" for perfumeString
"bfdr:hfgd46dG" for veryLongString
In short, my issue is finding the length of the string *input points to. As far as I understand it that won't be happening without making something really sketchy.
Am I correct in assuming the length cannot be acquired in a good way?
And if so would it be a horrible idea to do, for example:
char stringToProcessTemp1[50];
char stringToProcessTemp2[50];
char stringToProcess[50];
for (int i = 0; i < 50; i++) {
stringToProcessTemp1[i] = input + i;
}
for (int i = 0; i < 50; i++) {
stringToProcessTemp2[i] = input + i;
}
for (int i = 0; i < 50; i++) {
if (stringToProcessTemp1[i] == stringToProcessTemp2[i]) {
stringToProcessTemp[i] = stringToProcessTemp1[i];
}
}
Later checking where the first empty index is and saving everything before it as the used String as from my very limited experience in C when you go outside of an array you tend to get different outputs every time therefore making the chance both Temp strings match for an extra element directly after the last one of the original string what I'd consider low enough.
It's honestly the only idea I've got right now.
Finding the length of a string is no problem. strlen will do that for you. However, you don't even need that.
You can use the strstr function to find a substring within a string, in this case "::". When you find one, keep looking right after the last one you found until you don't find it anymore, then the last one you found is the one you want. Then you want the substring that starts right after it.
char *extract(char *input)
{
char *last = NULL, *start = input, *curr;
while ((curr == strstr(start, "::")) != NULL) {
last = curr; // keep track of the last "::" found
start = last + 1; // move the starting string to right after the last "::"
// move up 1 instead of 2 in case of ":::"
}
if (last != NULL) {
last +=2; // We found one; move just past the "::"
}
return last;
}
C strings, which are really only an array of characters, are by definition terminated by '\0'. So, for a well formed C string you can always get the length of the string by using strlen().
If, however, your string is not null-terminated, there is no way to determine it's length, and it is not a C string by definition any more, but just an array of characters.
I'm learning C programming and I'm having some issues to print a name that i store in a char array.
char nameArr[125];
for (int i = 0; i < 125; i++)
{
if (nameArr[i] != "\0")
{
printf(nameArr[i]);
}
else
{
i = 125;
}
}
This is my code in which I try to print out a name like "Joe Doe" that I already stored in the char array, but I get some errors in the compiler when I run this.
If I'm not suppose to do like this, how can I print out just the name and not all the 125 slots of the array?
Assuming your nameArr already contains a string, which is defined as a sequence of characters ending with 0, the obvious solution is to do
printf("%s", nameArr);
or
puts(nameArr); // appends newline automatically
If your question is how you would do this by hand, it would look something like this:
for (size_t i = 0; nameArr[i]; ++i)
{
putchar(nameArr[i]);
// or printf("%c", nameArr[i]);
}
nameArr[i] evaluates as true as long as this isn't a 0 byte. Also, always use size_t for array indices. int is not guaranteed to hold any size an object in C can have.
I've searched around for a quiet some time but surprisingly I couldn't find an answer to it:
I want to rewrite a char array starting from [0], but all what's happening is: it's always appending. Here's my code:
The algorithm is: I have a very long string which I like to break into several lines (wherever there is a blank space at the end of a line). Each line shall be saved in an array Index (lineContent);
void print_text(char* content, int menu_width, int which_selected, int menu_height, int scroll_pos)
{
int posCounter = 0;
int charCounter = menu_width-10;
int printOutCounter;
char* lineContent[400]; // 400 lines max
short spaceFound;
while (strlen(content) > menu_width) // If string is longer than 1 line
{
//Interesting Part ---------- START
char changeString [strlen(content)];
char printString [menu_width-10];
spaceFound = 0;
charCounter = menu_width-10;
lineContent[posCounter] = malloc(MAXITEMSTR);
while (spaceFound == 0)
{
if (content[charCounter] == ' ')
{
// I guess the error goes between here ...
strncpy(changeString,content,strlen(content));
strncpy(printString,content,menu_width-10);
// ...and here
memmove(&changeString[0], &changeString[charCounter], strlen(content));
content=changeString;
lineContent[posCounter]=printString;
strcat(lineContent[posCounter],"\0");
posCounter++;
spaceFound = 1;
//Interesting Part ---------- END
}
charCounter--;
if (charCounter <= 0)
spaceFound = 1;
}
}
}
As I said, in the end, when checking the content of lineContent, every entry is the same (the one from the last line).
I think this is because, strcpy just appends to the end, therefor I have to clear the array, to erase the former line. So it will start from [0] and not from the last printed letter.
Has anybody an idea how to do this? Is there a function that overwrites a char array instead of appending it?
Kind Regards
Strcat appends to the end, strcpy overwrites the value stored in the string.
Im working on a project and I am stumped on this part.
I need to read words from stdin and place them in a char array and use an array of pointers to point to each word since they will be jagged. where numwords is an int read in representing the number of words.
char words[10000];
char *wordp[2000];
the problem is that I can only use the pointers to add the words.I can no longer use the [] to help.
*wordp = words; //set the first pointer to the beginning of the char array.
while (t < numwords){
scanf("%s", *(wordp + t)) //this is the part I dont know
wordp = words + charcounter; //charcounter is the num of chars in the prev word
t++;
}
for(int i = 0;words+i != '\n';i++){
charcounter++;
}
any help would be great I am so confused when it comes to pointers and arrays.
Your code will be much more manageable if you use an additional pointer
reference and increment that directly. In this way you won't have to do any
mental math. Additionally you need to be incrementing the reference before
reading in the next string, scanf doesn't move the pointer for you.
char buffer[10000];
char* words[200];
int number_of_words = 200;
int current_words_index = 0;
// This is what we are going to use to write to the buffer
char* current_buffer_prt = buffer;
// quick memset (as I don't remember if c does this for us)
for (int i = 0; i < 10000; i++)
buffer[i] = '\0';
while (current_words_index < number_of_words) {
// Store a pointer to the current word before doing anything to it
words[current_word_index] = current_buffer_ptr;
// Read the word into the buffer
scanf("%s", current_buffer_ptr);
// NOTE: The above line could also be written
// scanf("%s", words[current_word_index]);
// this is how we move the buffer to it's next empty position.
while (current_buffer_ptr != '\n')
current_buffer_ptr++;
// this ensures we don't overwrite the previous \n char
current_buffer_ptr++;
current_words_index += 1;
}
What you want to do is relatively straightforward. You've got an array of 10,000 chars for storage, and 2000 pointers. So to start with you'll want to assign the first pointer to the start of the array:
wordp[0] = &words[0];
In pointer form this is:
*(wordp + 0) = words + 0;
I've used the zeros to show how it relates to the arrays. In general, to set each pointer to each element:
*(wordp + i) == wordp[i]
words + i == &words[i]
So all you need to do is keep track of where you are in the pointer array, and as long as you've assigned correctly, the pointer array will keep track of the position in your char array.