Problems freeing memory using free() - c

I have been trying to write a function that will insert commas into a binary number.
Below is my best attempt. It does work if I do NOT try to free() the memory.
If I try to free() the memory, I get an error.
I am puzzled. Please let me know what I am doing wrong.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int insertCommasIntoBinaryNumber(char* outstring, char* instring)
{
char *ptr, *optr;
int i, length, commas;
// move ptr to end of instring
for ( ptr = instring; *ptr; ptr++ );
//calculate offset with commas
length = ptr - instring;
commas = ( length - 1 ) / 8;
optr = outstring + length + commas;
//copy instring into outstring backwards inserting commas
*optr-- = *ptr--;
for ( i = 1; ptr >= instring; i++ )
{
*optr-- = *ptr--;
if ( ( i % 8 ) == 0 )
*optr-- = ',';
}
}
int main (void)
{
const int arrayDimension = 100;
char* instring = (char*) malloc(sizeof(char) * arrayDimension);
char* outstring = (char*) malloc(sizeof(char) * arrayDimension);
strncpy(instring, "111111110101010100001100", arrayDimension-1);
insertCommasIntoBinaryNumber(outstring, instring);
/* show the result */
printf ( "%s\n", outstring );
free(instring);
free(outstring);
}
Here is the output:
11111111,01010101,00001100
*** Error in `./a.out': free(): invalid next size (fast): 0x0000000000bc8010 ***
P.S. Many thanks for letting me know where the code was crashing on the 24th iteration. I soon realized that I was not calculating the number of commas needed correctly and not keeping track of the number of commas being inserted. After I did that, the code below appears to work fine now.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int insertCommasIntoBinaryNumber(char* const outString, const char* const inString)
{
char const *iptr; // iptr will be a pointer to the
// constant inString char array.
char *optr;
int i, commaCount;
// move iptr to end of inString
for ( iptr = inString; *iptr; iptr++ );
// Calculate Number of Commas Needed
const int inStringLength = iptr - inString;
const double totalNumberOfCommasFP = (( inStringLength ) / 8.0) - 1.0;
const int totalNumberOfCommas = (int) ceil(totalNumberOfCommasFP);
// Set optr
optr = outString + inStringLength + totalNumberOfCommas;
//copy inString into outString backwards inserting commas
*optr-- = *iptr--;
commaCount = 0;
for ( i = 1; iptr >= inString; i++ )
{
*optr-- = *iptr--;
if ( ( ( i % 8 ) == 0 ) && (commaCount < totalNumberOfCommas) )
{
*optr-- = ',';
commaCount++;
}
}
}
int main (void)
{
const char testString[] = "111111110101010100001100";
const int inStringArrayDimension = strlen(testString) + 1;
char * inString = (char*) malloc(sizeof(char) * inStringArrayDimension);
strncpy(inString, testString, inStringArrayDimension);
const int inStringLength = (int) strlen(inString);
const double totalNumberOfCommasFP = (( inStringLength ) / 8.0) - 1.0;
const int totalNumberOfCommas = (int) ceil(totalNumberOfCommasFP);
const int outStringArrayDimension = inStringArrayDimension + totalNumberOfCommas;
char* outString = (char*) malloc(sizeof(char) * outStringArrayDimension);
insertCommasIntoBinaryNumber(outString, inString);
/* show the result */
printf ( "%s\n", outString );
free(inString);
free(outString);
exit (EXIT_SUCCESS);
}
And here is the output:
11111111,01010101,00001100

Since the string length is 24, for ( i = 1; ptr >= instring; i++ ) iterates 24 times. On the 24th iteration, optr points to the first character of outstring. Since (i % 8) == 0 is true, *optr-- = ','; is executed. That puts a comma before outstring, writing outside array bounds and corrupting your program’s memory.

I recommend that you do this
#include <assert.h>
//copy instring into outstring backwards inserting commas
assert (optr >= outstring);
*optr-- = *ptr--;
for ( i = 1; ptr >= instring; i++ )
{
assert (optr >= outstring);
*optr-- = *ptr--;
if ( ( i % 8 ) == 0 ) {
assert (optr >= outstring);
*optr-- = ',';
}
}
Then when the assertion goes off, debug it. You have almost certainly botched the space calculation, under-estimating how much space is needed to store the version of the datum with commas inserted.
Secondly, you're doing something that ISO C does not require to work: incrementing pointers below the start of an object. This is not the actual problem; even if you debug the malloc corruption, that issue is still there.
What I'm getting at is that this is not a correct idiom:
for (ptr = end_of_object; ptr >= start_of_object; ptr--)
{
// ... loop body in which ptr is dereferenced
}
Here is why. When the last iteration of the loop occurs, ptr == start_of_object holds. The body of the loop is executed, and then, unconditionally, the ptr-- decrement is executed. Even though we do not execute the loop body any more, and therefore do not dereference ptr, it is still incorrect to be decrementing it. It is undefined behavior according to ISO C.
The idiom works in machine languages.
One way to avoid it is to use integer indexing.
for (i = num_elements - 1; i >= 0; i--)
{
// work with array[i]
}
Here, i is assumed to be a signed integer type. At the top of the last iteration, i == 0 holds. Then, unconditionally, i is decremented to -1. Since array[i] is never accessed in this case, that is completely safe.
Lastly, a robust, production version of this type of code cannot just assume that you have all the space in the destination array. Your comma-inserting API needs to provide some means by which the caller can determine how much space is required. E.g.:
const char *str = "1110101101";
// determine how much space is needed for string with commas
size_t space = comma_insert_space_required(str);
// OK, allocate that much space
char *str_with_commas = malloc(space);
// now process the same string into that space
comma_insert(str_with_commas, str);
This will work whether you have a five character input or five thousand.
If you choose an approach involving artificial limits in there like 100 bytes (the idea being no valid inputs will ever occur that come close), you still need defenses against that, so that you don't access an object out of bounds. "Bad guys" trying to break your software will look for ways to sneak in the "never occur" inputs.

Related

Replacing words in a string with words given in a 2D array

I'm currently working on a program that corrects given words in a sentence to be more polite.
I'm building a function that is given the original sentence and a 2D array, that stores the words we should look for and the ones we will replace them with.
This is my main function where the "dictionary" is declared:
int main(){
const char * d1 [][2] =
{
{ "hey", "hello" },
{ "bro", "sir" },
{ NULL, NULL }
};
printf("%s\n", newSpeak("well hey bro", d1) );
}
This functions job is to go through every pointer of the original string and check it with the first character of each word, that could potentially be 'bad'. If it catches the first letter, then it will go through the rest of the word and if it goes all the way to the end of the word, it will skip the original word and replace it with the 'good' word.
This is the function itself:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
char * newSpeak ( const char * text, const char * (*replace)[2] )
{
char * result = (char*)malloc( sizeof(char) );
int resIndex = 0; // Pointer to final text
int matches = 0; // 1 - Matches word from library, 0 - Does not
// Run through the whole original text
for ( int index = 0; text[index] != '\0'; index++ ){
for ( int line = 0; replace[line][0] != NULL; line++ ){
// If the first letter of the word matches, do the others match too?
// If yes, don't rewrite the original word, skip it, and write the replacement one by one.
if ( replace[line][0][0] == text[index] ){
matches = 1;
// Check one by one if letters from the word align with letters in the original string
for ( int letter = 0; replace[line][0][letter] != '\0'; letter++ ){
if ( replace[line][0][letter] != text[index + letter] ){
matches = 0;
break;
}
}
// If the whole word matches, skip what would be copied from original text (the bad word) and put in replacement letter by letter
if ( matches == 1 ){
// Push pointer of original string after the word
index += strlen( replace[line][0] );
for ( int r = 0; r < strlen( replace[line][1] ); r++){
result = (char*)realloc(result, (strlen( result ) + 1) * sizeof(char));
result[resIndex + r] = replace[line][1][r];
index += r;
}
}
}
}
if ( matches == 0 ){
result = (char*)realloc(result, (strlen( result ) + 1) * sizeof(char));
result[resIndex] = text[index];
}
resIndex++;
}
return result;
}
After this is run, my expected outcome is well hello sir, but instead, the function only returns well hello.
I am looking for an explanation to why the loop would stop and not check for the rest of the string, any help would be appreciated.
At least this problem:
strlen( result ) in result = (char*)realloc(result, (strlen( result ) + 1) * sizeof(char)); is not valid as result does not point to a string. Missing null character.

Convert String into Array of Strings in C

I'm trying to divide a string of alphabetically sorted words char *str = "a/apple/arm/basket/bread/car/camp/element/..."
into an array of strings alphabetically like so:
arr[0] = "a/apple/arm"
arr[1] = "basket/bread"
arr[2] = "car/camp"
arr[3] = ""
arr[4] = "element"
...
I'm not very skilled in C, so my approach was going to be to declare:
char arr[26][100];
char curr_letter = "a";
and then iterate over each char in the string looking for "/" follow by char != curr_letter, then strcpy that substring to the correct location.
I'm not sure if my approach is very good, let alone how to implement it properly.
Any help would be greatly appreciated!
So we basically loop through the string, and check if we found the "split character' and we also check that we didn't find the 'curr_letter' as the next character.
We keep track of the consumed length, the current length (used for memcpy later to copy the current string to the array).
When we find a position where we can add the current string to the array, we allocate space and copy the string to it as the next element in the array. We also add the current_length to consumed, and the current_length is reset.
We use due_to_end to find out if we have a / in the current string, and remove it accordingly.
Try:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *str = "a/apple/arm/basket/bread/car/camp/element/...";
char split_char = '/';
char nosplit_char = 'a';
char **array = NULL;
int num_elts = 0;
// read all the characters one by one, and add to array if
// your condition is met, or if the string ends
int current_length = 0; // holds the current length of the element to be added
int consumed = 0; // holds how much we already added to the array
for (int i = 0; i < strlen(str); i++) { // loop through string
current_length++; // increment first
int due_to_end = 0;
if ( ( str[i] == split_char // check if split character found
&& ( i != (strlen(str) - 1) // check if its not the end of the string, so when we check for the next character, we don't overflow
&& str[i + 1] != nosplit_char ) ) // check if the next char is not the curr_letter(nosplit_char)
|| (i == strlen(str) - 1 && (due_to_end = 1))) { // **OR**, check if end of string
array = realloc(array, (num_elts + 1) * sizeof(char *)); // allocate space in the array
array[num_elts] = calloc(current_length + 1, sizeof(char)); // allocate space for the string
memcpy(array[num_elts++], str + consumed, (due_to_end == 0 ? current_length - 1 : current_length)); // copy the string to the current array offset's allocated memory, and remove 1 character (slash) if this is not the end of the string
consumed += current_length; // add what we consumed right now
current_length = 0; // reset current_length
}
}
for (int i = 0; i < num_elts; i++) { // loop through all the elements for overview
printf("%s\n", array[i]);
free(array[i]);
}
free(array);
}
Yes, the approach that you specify in your question seems good, in principle. However, I see the following problem:
Using strcpy will require a null-terminated source string. This means if you want to use strcpy, you will have to overwrite the / with a null character. If you don't want to have to modify the source string by writing null characters into it, then an alternative would be to use the function memcpy instead of strcpy. That way, you can specify the exact number of characters to copy and you don't require the source string to have a null terminating character. However, this also means that you will somehow have to count the number of characters to copy.
On the other hand, instead of using strcpy or memcpy, you could simply copy one character at a time from str into arr[0], until you encounter the next letter, and then copy one character at a time from str into arr[1], and so on. That solution may be simpler.
In accordance with the community guidelines for homework questions, I will not provide a full solution to your problem at this time.
EDIT: Since another answer has already provides a full solution which uses memcpy, I will now also provide a full solution, which uses the simpler solution mentioned above of copying one character at a time:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define NUM_LETTERS 26
#define MAX_CHARS_PER_LETTER 99
int main( void )
{
//declare the input string
char *str =
"a/apple/arm/basket/bread/car/camp/element/"
"frog/glass/saddle/ship/water";
//declare array which holds all the data
//we must add 1 for the terminating null character
char arr[NUM_LETTERS][MAX_CHARS_PER_LETTER+1];
//this variable will store the current letter that we
//have reached
char curr_letter = 'a';
//this variable will store the number of chars that are
//already used in the current letter, which will be a
//number between 0 and MAX_CHARS_PER_LETTER
int chars_used = 0;
//this variable stores whether the next character is
//the start of a new word
bool new_word = true;
//initialize the arrays to contain empty strings
for ( int i = 0; i < NUM_LETTERS; i++ )
arr[i][0] = '\0';
//read one character at a time
for ( const char *p = str; *p != '\0'; p++ )
{
//determine whether we have reached the end of a word
if ( *p == '/' )
{
new_word = true;
}
else
{
//determine whether we have reached a new letter
if ( new_word && *p != curr_letter )
{
//write terminating null character to string of
//previous letter, overwriting the "/"
if ( chars_used != 0 )
arr[curr_letter-'a'][chars_used-1] = '\0';
curr_letter = *p;
chars_used = 0;
}
new_word = false;
}
//verify that buffer is large enough
if ( chars_used == MAX_CHARS_PER_LETTER )
{
fprintf( stderr, "buffer overflow!\n" );
exit( EXIT_FAILURE );
}
//copy the character
arr[curr_letter-'a'][chars_used++] = *p;
}
//the following code assumes that the string pointed to
//by "str" will not end with a "/"
//write terminating null character to string
arr[curr_letter-'a'][chars_used] = '\0';
//print the result
for ( int i = 0; i < NUM_LETTERS; i++ )
printf( "%c: %s\n", 'a' + i, arr[i] );
}
This program has the following output:
a: a/apple/arm
b: basket/bread
c: car/camp
d:
e: element
f: frog
g: glass
h:
i:
j:
k:
l:
m:
n:
o:
p:
q:
r:
s: saddle/ship
t:
u:
v:
w: water
x:
y:
z:
Here is another solution which uses strtok:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_LETTERS 26
#define MAX_CHARS_PER_LETTER 99
int main( void )
{
//declare the input string
char str[] =
"a/apple/arm/basket/bread/car/camp/element/"
"frog/glass/saddle/ship/water";
//declare array which holds all the data
//we must add 1 for the terminating null character
char arr[NUM_LETTERS][MAX_CHARS_PER_LETTER+1];
//this variable will store the current letter that we
//have reached
char curr_letter = 'a';
//this variable will store the number of chars that are
//already used in the current letter, which will be a
//number between 0 and MAX_CHARS_PER_LETTER
int chars_used = 0;
//initialize the arrays to contain empty strings
for ( int i = 0; i < NUM_LETTERS; i++ )
arr[i][0] = '\0';
//find first token
char *p = strtok( str, "/" );
//read one token at a time
while ( p != NULL )
{
int len;
//determine whether we have reached a new letter
if ( p[0] != curr_letter )
{
curr_letter = p[0];
chars_used = 0;
}
//count length of string
len = strlen( p );
//verify that buffer is large enough to copy string
if ( chars_used + len >= MAX_CHARS_PER_LETTER )
{
fprintf( stderr, "buffer overflow!\n" );
exit( EXIT_FAILURE );
}
//add "/" if necessary
if ( chars_used != 0 )
{
arr[curr_letter-'a'][chars_used++] = '/';
arr[curr_letter-'a'][chars_used] = '\0';
}
//copy the word
strcpy( arr[curr_letter-'a']+chars_used, p );
//update number of characters used in buffer
chars_used += len;
//find next token
p = strtok( NULL, "/" );
}
//print the result
for ( int i = 0; i < NUM_LETTERS; i++ )
printf( "%c: %s\n", 'a' + i, arr[i] );
}

C allocation memory error. Don't find something like this

Could you help please ?
When I execute this code I receive that:
AAAAABBBBBCCCCCBBBBBCOMP¬ıd┐╔ LENGTH 31
There are some weirds characters after letters, while I've allocate just 21 bytes.
#include <stdio.h>
#include <stdlib.h>
char * lineDown(){
unsigned short state[4] = {0,1,2,1};
char decorationUp[3][5] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
char * deco = malloc(21);
int k;
int p = 0;
for(int j = 0; j < 4; j++){
k = state[j];
for(int i = 0; i < 5; i++){
*(deco+p) = decorationUp[k][i];
p++;
}
}
return deco;
}
int main(void){
char * lineDOWN = lineDown();
int k = 0;
char c;
do{
c = *(lineDOWN+k);
printf("%c",*(lineDOWN+k));
k++;
}while(c != '\0');
printf("LENGTH %d\n\n",k);
}
The function does not build a string because the result array does not contain the terminating zero though a space for it was reserved when the array was allocated.
char * deco = malloc(21);
So you need to append the array with the terminating zero before exiting the function
//...
*(deco + p ) = '\0';
return deco;
}
Otherwise this do-while loop
do{
c = *(lineDOWN+k);
printf("%c",*(lineDOWN+k));
k++;
}while(c != '\0')
will have undefined behavior.
But even if you will append the array with the terminating zero the loop will count the length of the stored string incorrectly because it will increase the variable k even when the current character is the terminating zero.
Instead you should use a while loop. In this case the declaration of the variable c will be redundant. The loop can look like
while ( *( lineDOWN + k ) )
{
printf("%c",*(lineDOWN+k));
k++;
}
In this case this call
printf("\nLENGTH %d\n\n",k);
^^
will output the correct length of the string equal to 20.
And you should free the allocated memory before exiting the program
free( lineDOWN );
As some other wrote here in their answers that the array decorationUp must be declared like
char decorationUp[3][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
then it is not necessary if you are not going to use elements of the array as strings and you are not using them as strings in your program.
Take into account that your program is full of magic numbers. Such a program is usually error-prone. Instead you should use named constants.
In
char decorationUp[3][5] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
your string needs 6 characters to also place the null char, even in that case you do not use them as 'standard' string but only array of char. To get into the habit always reverse the place for the ending null character
you can do
char decorationUp[3][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
Note it is useless to give the first size, the compiler counts for you
Because in main you stop when you read the null character you also need to place it in deco at the end, so you need to allocate 21 for it. As before you missed the place for the null character, but here that produces an undefined behavior because you read after the allocated block.
To do *(deco+p) is not readable, do deco[p]
So for instance :
char * lineDown(){
unsigned short state[] = {0,1,2,1};
char decorationUp[][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
char * deco = malloc(4*5 + 1); /* a formula to explain why 21 is better than 21 directly */
int k;
int p = 0;
for(int j = 0; j < 4; j++){
k = state[j];
for(int i = 0; i < 5; i++){
deco[p] = decorationUp[k][i];
p++;
}
}
deco[p] = 0;
return deco;
}

Don't understand why C program crashes, pointer array of strings

I'm having trouble with this for loop and I don't understand why it crashes. I'm trying to read an input list of 20 names in "first name last name" format and storing them as a string in "last name, first name". Duplicates should not be stored into the array pointer.
When I comment out the malloc and compare loop, apparently there is some issue with the address staying the same, so that *ary returns the same value as *walker. The filePtr works and the strcpy and strcat functions have no issues. Also, removing the first printf also causes the program to crash, even though removing it doesn't seem it should have any real effect besides output.
FILE *filePtr = fopen ("input.txt","r");
int size = 20;
char **ary;
char **walker;
char **end;
int strsize = 0;
char firstname[30] = {0};
char lastname[30] = {0};
char *fullname;
ary = calloc (size, sizeof(char *));
printf("%d\n",sizeof(pAry));
for ( walker = ary ; *walker < (*end = *ary + size) ; walker++)
{
fscanf(filePtr," %s",firstname);
fscanf(filePtr," %[^\n]",lastname);
strsize = strlen(firstname) + strlen(lastname) + 3;
fullname = malloc (strsize * sizeof(char));
strcpy(fullname,lastname);
strcat(fullname,", ");
strcat(fullname,firstname);
for ( compare = 0 ; compare < walker ; compare++)
{
if(strcmp(fullname,*(ary + compare)) != 0)
{
diff = 0;
}
}
if (diff)
{
strncpy(*walker,fullname,strsize);
printf("%s\n",*walker);
}
free(fullname);
}
The outer loop shall loop over all entries of ary, so the end condition shall test for walker being (at) the end.
No dereferencing is needed here:
for (walker = ary; walker < (end = ary + size); walker++)
The test loop for duplicates does compare againt absolute pointers values, the initialisation of compare to 0 implies relative comparsion so this line
compare < walker;
should be
compare < (walker - ary);
Substracting two pointers returns an integer, its size depends on the size of a pointer, which differs depending on compiler and/or system. To get around this uncertainty the integer type ptrdiff_t had been introduced to be guaranteed to hold any pointer difference.
So compare shall be declare:
ptrdiff_t compare;
strcmp() returns 0 if the strings to be compared are equal, so setting diff to 0 on inequality is wrong.
You might like to use the following statement to set diff:
diff = strcmp(fullname,*(ary + compare));
This sets diff to 0 (false) if the two string a equal (not *diff*erent).
Also comparision shall stop after a dupe had been found.
if (!diff)
{
break;
}
Finally diff needs to be (re-)initialised for every iteration.
Instead of
strncpy(*walker, fullname, strsize);
do
*walker = fullname;
as fullname referrs to the freshly allocated memory and needs to be stored, as overwritten in the next iteration.
The line free()ing fullname
free(fullname);
needs to be removed then.
Putting all this together you get:
...
for (walker = ary; walker < (end = ary + size); walker++)
{
...
{
int diff = 1;
for (ptrdiff_t compare = 0; compare < (walker - ary); compare++)
{
diff = strcmp(fullname, *(ary + compare));
if (!diff)
{
break;
}
}
if (diff)
{
*walker = fullname;
printf("%s\n", *walker);
}
}
}

pointers and string parsing in c

I was wondering if somebody could explain me how pointers and string parsing works. I know that I can do something like the following in a loop but I still don't follow very well how it works.
for (a = str; * a; a++) ...
For instance, I'm trying to get the last integer from the string. if I have a string as const char *str = "some string here 100 2000";
Using the method above, how could I parse it and get the last integer of the string (2000), knowing that the last integer (2000) may vary.
Thanks
for (a = str; * a; a++) ...
This works by starting a pointer a at the beginning of the string, until dereferencing a is implicitly converted to false, incrementing a at each step.
Basically, you'll walk the array until you get to the NUL terminator that's at the end of your string (\0) because the NUL terminator implicitly converts to false - other characters do not.
Using the method above, how could I parse it and get the last integer of the string (2000), knowing that the last integer (2000) may vary.
You're going to want to look for the last space before the \0, then you're going to want to call a function to convert the remaining characters to an integer. See strtol.
Consider this approach:
find the end of the string (using that loop)
search backwards for a space.
use that to call strtol.
-
for (a = str; *a; a++); // Find the end.
while (*a != ' ') a--; // Move back to the space.
a++; // Move one past the space.
int result = strtol(a, NULL, 10);
Or alternatively, just keep track of the start of the last token:
const char* start = str;
for (a = str; *a; a++) { // Until you hit the end of the string.
if (*a == ' ') start = a; // New token, reassign start.
}
int result = strtol(start, NULL, 10);
This version has the benefit of not requiring a space in the string.
You just need to implement a simple state machine with two states, e.g
#include <ctype.h>
int num = 0; // the final int value will be contained here
int state = 0; // state == 0 == not parsing int, state == 1 == parsing int
for (i = 0; i < strlen(s); ++i)
{
if (state == 0) // if currently in state 0, i.e. not parsing int
{
if (isdigit(s[i])) // if we just found the first digit character of an int
{
num = s[i] - '0'; // discard any old int value and start accumulating new value
state = 1; // we are now in state 1
}
// otherwise do nothing and remain in state 0
}
else // currently in state 1, i.e. parsing int
{
if (isdigit(s[i])) // if this is another digit character
{
num = num * 10 + s[i] - '0'; // continue accumulating int
// remain in state 1...
}
else // no longer parsing int
{
state = 0; // return to state 0
}
}
}
I know this has been answered already but all the answers thus far are recreating code that is available in the Standard C Library. Here is what I would use by taking advantage of strrchr()
#include <string.h>
#include <stdio.h>
int main(void)
{
const char* input = "some string here 100 2000";
char* p;
long l = 0;
if(p = strrchr(input, ' '))
l = strtol(p+1, NULL, 10);
printf("%ld\n", l);
return 0;
}
Output
2000
for (a = str; * a; a++)...
is equivalent to
a=str;
while(*a!='\0') //'\0' is NUL, don't confuse it with NULL which is a macro
{
....
a++;
}
The loop you've presented just goes through all characters (string is a pointer to the array of 1-byte chars that ends with 0). For parsing you should use sscanf or better C++'s string and string stream.

Resources