So I have a string which will have the following rough format: string # more than one string here.
What I want to do is strip everything after the #. How would I do that? Furthermore, what if I just want to keep the initial string, and take everything after the space and the #?
I have the following code, but obviously appending something to a NULL string does not work as expected:
char *inst_ptr holds the whole string.
char *lbl = NULL;
int len = 0;
size_t inst_len = strlen(inst_ptr);
for (int t = 0; t < inst_len; t++) {
if (inst_ptr[t] == '#')
break;
else {
printf("len %d\n", len);
lbl[len] = inst_ptr[t];
lbl[len+1] = '\0';
len = strlen(lbl);
}
}
EDIT:
Basically, assume I have the following string:
loop # hello world!
I just want to extract loop in another string. What I am doing above is having lbl as a NULL string, and run a loop across the original string. As long as the character is not #, i just "append" the character with a null terminator as shown above.
Perhaps you should check section 7.21 in the standard for some inspiration.
The best approach depends on the rest of your application.
If you don't care about the original data, you could just use
strtok(inst_ptr, "#");
Or it might be better to allocate-and-copy just the data you need:
char * temp = strchr(inst_ptr, '#');
char * lbl;
if (temp)
lbl = strndup(inst_ptr, temp - inst_ptr);
else
lbl = strdup(inst_ptr);
Please note that the above are the minimal implemenations I've come to think of off the top of my head, not necessarily the best ones.
First, you are doing
char *lbl = NULL;
Then you are doing
lbl[len]
You're trying to dereference a NULL pointer and causing undefined behaviour.
First, you need to allocate memory for that string (calloc allocates the memory and sets it all to 0, which will obviate the need to manually add the null terminator):
char *lbl = calloc(inst_len + 1, 1);
Then you need to fix your loop, some of the things are in the wrong place. It should be
for (int t = 0; t < inst_len; t++) {
if (inst_ptr[t] == '#') {
len = t - 1; // strlen(lbl) is redundant
break;
} else
lbl[t] = inst_ptr[t];
}
Then when you are done, free the memory you allocated so as not to cause a memory leak:
free(lbl);
Related
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.
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.
Say I have a birthday that is written as 04251993 in some file that
I want to format it as 04/25/1993
I'm assuming that I should make an empty string, or modify the old string into the new string.
I'm not quite sure of how to do that: need some help on writing the function.
I started it out like this.
the first two chars need to be the month with a slash after, 2 more chars with a slash after and then lasty 4 more chars to put out the year.
void timef(char str[]){
printf("%c, str[0]) ?
Make a character array large enough on the heap. Then go through the
characters and insert the slashes. Use fputs to place it in a file. Repeat.
Use "%.*s" to scan the original string and then write to a new one
const char *src = "04251993";
char dest[11];
if (strlen(src) >= 8) {
sprintf(dest, "%.2s/%.2s/%.4s", src, src + 2, src + 4);
}
You can either write a function that is general or one that only performs an operation within set bounds. For this answer, let's just work on the latter. This means, I'll assume your string is always a fixed size of 9 chars (including '\0') and the packing of the data is "mm/dd/yyyy".
From there, you just need to work out how much larger the new string needs to be, and that's originalString + 2 chars, so you need a new array of 11 characters.
char newDate[11] = "";
Then you need to loop through the contents of the original string array and place each character into the new array, as well as adding the slashes as you go. So something like this:
int main()
{
int newSize = 11;
char oldDate[9] = "04231993";
char newDate[11] = "";
for(int i = 0, j = 0; i < newSize && j < oldSize; i++, j++){
if(i == 2){
newDate[i] = '/';
i++;
}
if(i == 5){
newDate[i] = '/';
i++;
}
newDate[i] = oldDate[j];
}
printf("%s", newDate);
}
That's REALLY simple and only to illustrate the basic concept. I would recommend working on your own, more robust version.
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.
I understand that a lot of people here complain about strcpy, but I haven't found anything using search that addresses the issue I have.
First off, calling strcpy itself doesn't cause any sort of crash/segmentation fault itself. Secondly, the code is contained within a function, and the first time that I call this function it works perfectly. It only crashes on the second time through.
I'm programming with the LPC1788 microcontroller; memory is pretty limited, so I can see why things like malloc may fail, but not free.
The function trimMessage() contains the code, and the purpose of the function is to remove a portion of a large string array if it becomes too large.
void trimMessage()
{
int trimIndex;
// currMessage is a globally declared char array that has already been malloc'd
// and written to.
size_t msgSize = strlen(currMessage);
// Iterate through the array and find the first newline character. Everything
// from the start of the array to this character represents the oldest 'message'
// in the array, to be got rid of.
for(int i=0; i < msgSize; i++)
{
if(currMessage[i] == '\n')
{
trimIndex = i;
break;
}
}
// e.g.: "\fProgram started\r\nHow are you?\r".
char *trimMessage = (char*)malloc((msgSize - trimIndex - 1) * sizeof(char));
trimMessage[0] = '\f';
// trimTimes = the number of times this function has been called and fully executed.
// freeing memory just below is non-sensical, but it works without crashing.
//if(trimTimes == 1) { printf("This was called!\n"); free(trimMessage); }
strcpy(&trimMessage[1], &currMessage[trimIndex+1]);
// The following line will cause the program to crash.
if(trimTimes == 1) free(trimMessage);
printf("trimMessage: >%s<\n", trimMessage);
// Frees up the memory allocated to currMessage from last iteration
// before assigning new memory.
free(currMessage);
currMessage = malloc((msgSize - trimIndex + 1) * sizeof(char));
for(int i=0; i < msgSize - trimIndex; i++)
{
currMessage[i] = trimMessage[i];
}
currMessage[msgSize - trimIndex] = '\0';
free(trimMessage);
trimMessage = NULL;
messageCount--;
trimTimes++;
}
Thank you to everyone that helped. The function works properly now. To those asking why I was trying to print out an array I just freed, that was just there to show that the problem occurred after strcpy and rule out any other code that came after it.
The final code is here, in case it proves useful to anyone who comes across a similar problem:
void trimMessage()
{
int trimIndex;
size_t msgSize = strlen(currMessage);
char *newline = strchr(currMessage, '\n');
if (!newline) return;
trimIndex = newline - currMessage;
// e.g.: "\fProgram started\r\nHow are you?\r".
char *trimMessage = malloc(msgSize - trimIndex + 1);
trimMessage[0] = '\f';
strcpy(&trimMessage[1], &currMessage[trimIndex+1]);
trimMessage[msgSize - trimIndex] = '\0';
// Frees up the memory allocated to currMessage from last iteration
// before assigning new memory.
free(currMessage);
currMessage = malloc(msgSize - trimIndex + 1);
for(int i=0; i < msgSize - trimIndex; i++)
{
currMessage[i] = trimMessage[i];
}
currMessage[msgSize - trimIndex] = '\0';
free(trimMessage);
messageCount--;
}
free can and will crash if the heap is corrupt or if you pass it an invalid pointer.
Looking at that, I think your first malloc is a couple of bytes short. You need to reserve a byte for the null terminator and also you're copying into offset 1, so you need to reserve another byte for that. So what is going to happen is that your copy will overwrite information at the start of the next block of heap (often used for length of next block of heap and an indication as to whether or not it is used, but this depends on your RTL).
When you next do a free, it may well try to coalesce any free blocks. Unfortunately, you've corrupted the next blocks header, at which point it will go a bit insane.
Compare these two lines of your code (I've respaced the second line, of course):
char *trimMessage = (char*)malloc((msgSize - trimIndex - 1) * sizeof(char));
currMessage = malloc((msgSize - trimIndex + 1) * sizeof(char));
Quite apart from the unnecessary difference in casting (consistency is important; which of the two styles you use doesn't matter too much, but don't use both in the same code), you have a difference of 2 bytes in the length. The second is more likely to be correct than the first.
You allocated 2 bytes too few in the first case, and the copy overwrote some control information that malloc() et al depend on, so the free() crashed because you had corrupted the memory it manages.
In this case, the problem was not so much strcpy() as miscalculation.
One of the problems with corrupting memory is that the victim code (the code that finds the trouble) is often quite far removed from the code that caused the trouble.
This loop:
for(int i=0; i < msgSize; i++)
{
if(currMessage[i] == '\n')
{
trimIndex = i;
break;
}
}
could be replaced with:
char *newline = strchr(currMessage, '\n');
if (newline == 0)
...deal with no newline in the current messages...
trimIndex = newline - currMessage;
Add this code just before the malloc() call:
// we need the destination buffer to be large enough for the '\f' character, plus
// the remaining string, plus the null terminator
printf("Allocating: %d Need: %d\n", (msgSize - trimIndex - 1), 1 + strlen(&currMessage[trimIndex+1]) + 1);
And I think it will show you the problem.
It's been demonstrated time and again that hand calculating buffer sizes can be error prone. Sometimes you have to do it, but other times you can let a function handle those error prone aspects:
// e.g.: "\fProgram started\r\nHow are you?\r".
char *trimMessage = strdup( &currMessage[trimIndex]);
if (trimMessage && (trimMessage[0] == '\n')) {
trimMessage[0] = '\f';
}
If your runtime doesn't have strdup(), it's easy enough to implement (http://snipplr.com/view/16919/strdup/).
And as a final edit, here's an alternative, simplified trimMessage() that I believe to be equivalent:
void trimMessage()
{
char *newline = strchr(currMessage, '\n');
if (!newline) return;
memmove( currMessage, newline, strlen(newline) + 1);
currMessage[0] = '\f'; // replace '\n'
messageCount--;
}