PDA

View Full Version : Probably a simple C problem



TheStroj
April 14th, 2011, 07:25 PM
Hi everyone!

I'm working with a really long array of numbers and I ran into a really weird problem that I cannot fix. So I thought you might know ;D

I'm simply trying to print the array containing numbers, 1 number at time. It is exactly 1000 characters long. Code:



#include <stdio.h>

int main()
{
char numbers[1000]="73167176531330624919225119674426574742355349194934 96983520312774506326239578318016984801869478851843 85861560789112949495459501737958331952853208805511 12540698747158523863050715693290963295227443043557 66896648950445244523161731856403098711121722383113 62229893423380308135336276614282806444486645238749 30358907296290491560440772390713810515859307960866 70172427121883998797908792274921901699720888093776 65727333001053367881220235421809751254540594752243 52584907711670556013604839586446706324415722155397 53697817977846174064955149290862569321978468622482 83972241375657056057490261407972968652414535100474 82166370484403199890008895243450658541227588666881 16427171479924442928230863465674813919123162824586 17866458359124566529476545682848912883142607690042 24219022671055626321111109370544217506941658960408 07198403850962455444362981230987879927244284909188 84580156166097919133875499200524063689912560717606 05886116467109405077541002256983155200055935729725 71636269561882670428252483600823257530420752963450";

int i;

for(i=0; i<1000; i++)
{
printf("%d", numbers[i]);
}

return 0;
}

(I was cleaning the code in this window to make it more readable, I hope everything is still there, if not, just add it :P).


As a result I get numbers all mixed up.

Hopefully you can help :)

Thanks in advance!

Simian Man
April 14th, 2011, 07:32 PM
You actually have 1001 characters there. Even if you had 1000, you did not make room for the NULL terminator.

You real problem, however, is your printf code. You are using %d which is for decimal numbers. What you have isn't decimal numbers, though - they are characters. Changing the %d to %c produces the output you probably expect.

TheStroj
April 14th, 2011, 08:42 PM
You actually have 1001 characters there. Even if you had 1000, you did not make room for the NULL terminator.

You real problem, however, is your printf code. You are using %d which is for decimal numbers. What you have isn't decimal numbers, though - they are characters. Changing the %d to %c produces the output you probably expect.

I thought of everything but %c -.-
thanks for your help man :)

stchman
April 14th, 2011, 08:59 PM
All looks good.

Remember, when you do a %d on a character you will get its ASCII in dec. Use %c and this will give you the output you want.

7 = 55 in ASCII
3 = 51 in ASCII

Try this out.



#include <stdio.h>
#include <string.h>

int main()
{
char numbers[ 1000 ] = "73167176531330624919225119674426574742355349194934 96983520312774506326239578318016984801869478851843 85861560789112949495459501737958331952853208805511 12540698747158523863050715693290963295227443043557 66896648950445244523161731856403098711121722383113 62229893423380308135336276614282806444486645238749 30358907296290491560440772390713810515859307960866 70172427121883998797908792274921901699720888093776 65727333001053367881220235421809751254540594752243 52584907711670556013604839586446706324415722155397 53697817977846174064955149290862569321978468622482 83972241375657056057490261407972968652414535100474 82166370484403199890008895243450658541227588666881 16427171479924442928230863465674813919123162824586 17866458359124566529476545682848912883142607690042 24219022671055626321111109370544217506941658960408 07198403850962455444362981230987879927244284909188 84580156166097919133875499200524063689912560717606 05886116467109405077541002256983155200055935729725 71636269561882670428252483600823257530420752963450";

int i;

printf( "%d\n\n", strlen( numbers ) );


for( i = 0; i < 1000; i++)
{
printf( "%d", numbers[ i ] );
}

printf( "\n\n" );

for( i = 0; i < 1000; i++ )
{
printf( "%c", numbers[ i ] );
}

return 0;
}
Your character array is exactly 1000 characters.

r-senior
April 14th, 2011, 09:26 PM
Is it also worth adding that you don't need to specify the array dimensions when initializing from a constant? For example:



char numbers[] = "1234567890";


Then, of course, your loop becomes:



for (i = 0; i < strlen(numbers); i++) {
...
}


Which all makes the code more maintainable because you don't have to change multiple occurrences of 1000 if you change the length of the string. I know it's only an example but good habits are good habits.

(For clarity, I've ignored the fact that strlen is called many times).

stchman
April 14th, 2011, 09:48 PM
You actually have 1001 characters there. Even if you had 1000, you did not make room for the NULL terminator.

You real problem, however, is your printf code. You are using %d which is for decimal numbers. What you have isn't decimal numbers, though - they are characters. Changing the %d to %c produces the output you probably expect.

When you initialize a character array like that the compiler puts a null terminator on the end of the array for you. This would indeed make the array 1001 characters long.

He initialized it wrong and should have used the method r-senior suggested, otherwise the compiler will not put a null terminator.

The correct code would be:



#include <stdio.h>
#include <string.h>

int main()
{
char numbers[] = "73167176531330624919225119674426574742355349194934 96983520312774506326239578318016984801869478851843 85861560789112949495459501737958331952853208805511 12540698747158523863050715693290963295227443043557 66896648950445244523161731856403098711121722383113 62229893423380308135336276614282806444486645238749 30358907296290491560440772390713810515859307960866 70172427121883998797908792274921901699720888093776 65727333001053367881220235421809751254540594752243 52584907711670556013604839586446706324415722155397 53697817977846174064955149290862569321978468622482 83972241375657056057490261407972968652414535100474 82166370484403199890008895243450658541227588666881 16427171479924442928230863465674813919123162824586 17866458359124566529476545682848912883142607690042 24219022671055626321111109370544217506941658960408 07198403850962455444362981230987879927244284909188 84580156166097919133875499200524063689912560717606 05886116467109405077541002256983155200055935729725 71636269561882670428252483600823257530420752963450";

int i;

for( i = 0; i < sizeof( numbers) / sizeof( char ); i++ )
{
printf( "%c", numbers[ i ] );
}

return 0;
}

Simian Man
April 14th, 2011, 10:06 PM
When you initialize a character array like that the compiler puts a null terminator on the end of the array for you. This would indeed make the array 1001 characters long.


Obviously, but he actually included 1001 actual digits. At least that's what wc told me. So if he did want to specify the size, it would have to be 1002.

Phenax
April 14th, 2011, 10:20 PM
The correct code would be:


It's worth mentioning that sizeof(char) will always be 1 therefore it is not needed.

stchman
April 14th, 2011, 10:25 PM
Obviously, but he actually included 1001 actual digits. At least that's what wc told me. So if he did want to specify the size, it would have to be 1002.




#include <stdio.h>
#include <string.h>

int main( void )
{
char numbers[] = "73167176531330624919225119674426574742355349194934 96983520312774506326239578318016984801869478851843 85861560789112949495459501737958331952853208805511 12540698747158523863050715693290963295227443043557 66896648950445244523161731856403098711121722383113 62229893423380308135336276614282806444486645238749 30358907296290491560440772390713810515859307960866 70172427121883998797908792274921901699720888093776 65727333001053367881220235421809751254540594752243 52584907711670556013604839586446706324415722155397 53697817977846174064955149290862569321978468622482 83972241375657056057490261407972968652414535100474 82166370484403199890008895243450658541227588666881 16427171479924442928230863465674813919123162824586 17866458359124566529476545682848912883142607690042 24219022671055626321111109370544217506941658960408 07198403850962455444362981230987879927244284909188 84580156166097919133875499200524063689912560717606 05886116467109405077541002256983155200055935729725 71636269561882670428252483600823257530420752963450";

printf( "Number of elements in array numbers (sizeof) = %d\n\n", sizeof( numbers ) / sizeof( char ) );
printf( "Number of elements in array numbers (strlen) = %d\n\n", strlen( numbers ) );

return 0;
}

The resulting output is:



Number of elements in array numbers (sizeof) = 1001

Number of elements in array numbers (strlen) = 1000

stchman
April 14th, 2011, 10:28 PM
It's worth mentioning that sizeof(char) will always be 1 therefore it is not needed.

You are right, but I use that for the sake of clarity for when I do doubles, floats, ints, etc.

JupiterV2
April 15th, 2011, 12:23 AM
for( i = 0; i < sizeof( numbers) / sizeof( char ); i++ )

I realize this was just an example but is it not considered good practice to use the following:



int size = strlen (numbers); /* or sizeof (numbers) / sizeof (char); */

for (i = 0; i < size; i++) { ... }


This is because every time the for loop iterates, the statement
sizeof (numbers) / sizeof (char) is reevaluated, which can get quite costly.

Tony Flury
April 15th, 2011, 08:30 AM
I realize this was just an example but is it not considered good practice to use the following:



int size = strlen (numbers); /* or sizeof (numbers) / sizeof (char); */

for (i = 0; i < size; i++) { ... }


This is because every time the for loop iterates, the statement
sizeof (numbers) / sizeof (char) is reevaluated, which can get quite costly.

I think you will find that sizeof is calculated at compile time for this example, and therefore it does not matter that it is re-evaluated - although what might be re-evaluated is the division, and even then i would imagine that gcc and most other decent compilers would optimise expression away as it does not change.

Premature optimisation is the root of bad code.

Arndt
April 15th, 2011, 09:13 AM
Obviously, but he actually included 1001 actual digits. At least that's what wc told me. So if he did want to specify the size, it would have to be 1002.

Did you get a newline included when you used wc?

It seems gcc warns by default if the literal is too long:

"warning: initializer-string for array of chars is too long"