Why does the following C code produce negative numbers as output? And how do I prevent this from happening?
#include <stdio.h>
int main()
{
int i;
char buf[1024];
for (i = 0; i < 1024; i++)
buf[i] = i%256;
for (i=0; i<1024; i++) {
printf("%d ", buf[i]);
if (i%32==31)
printf("\n");
}
}
Let's look at this line of code:
buf[i] = i%256;
Here, i % 256 is computed as a value of type int. However, buf is an array of chars, so when the value is assigned into the array, it's truncated to a char. If the result of the modulus is outside of the range of positive values that can be stored in a char, it may end up wrapping around and being stored as a negative number instead.
In other words, it's not that the modulus produced a negative value as much as you stored the result in a type that can't hold it. Try changing the array to an int array or unsigned char array and see if that fixes things.
Hope this helps!
Related
This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
Closed 3 years ago.
Is there a way, I can use of strlen() to find the length of the arrays, instead of specifying in the loop.
First Code: Working With x < 4 Which is the size of the array of temps[4].
#include <stdio.h>
#include <string.h>
int main(){
float temps[4] = {72.5, 73.4, 74.7, 75.2};
int x;
printf("Local Temperatures\n");
for(x = 1; x < 4; x++){
printf("Station %d: %.1f\n",x,temps[x]);
}
}
My Second Code, Not Working, But Looking At What, I Am Trying To achieve with strlen() to find the size of the array.:
#include <stdio.h>
#include <string.h>
int main(){
float temps[4] = {72.5, 73.4, 74.7, 75.2};
int x;
float size;
size = temps;
printf("Local Temperatures\n");
for(x = 1; x < strlen(size); x++){
printf("Station %d: %.1f\n",x,size[x]);
}
}
strlen is effectively an optimized version of the following:
size_t len = 0;
const char *p = s;
while (!*p) {
++len;
++p;
}
You can easily adapt that.
size_t len = 0;
const float *p = s;
while (*p != 0.0) {
++len;
++p;
}
Of course, that means you need a sentinel value just like you had for the string.
float temps[] = { 72.5, 73.4, 74.7, 75.2, 0.0 };
While you can use a value other than 0.0 as your sentinel value, using a sentinel value might not be desirable, so you might not really want to take the same approach as one does for strings.
For an array (as opposed to a pointer), you can use the following to determine the number of elements in the array:
sizeof(a)/sizeof(*a)
That means you can use the following to determine the number of elements in temps:
sizeof(temps)/sizeof(*temps)
Simple method is to get the size of a array is by sizeof(temps)/sizeof(temps[0])
something like,
for(x = 0; x < sizeof(temps)/sizeof(temps[0]); x++){
printf("Station %d: %.1f\n",x,temps[x]);
}
Note: In your snippet array access is done from 1 to (size) instead 0 to (size-1) which is out of bound access.
Short answer: no.
strlen expects an argument of type char *, which points to the first character of a string, which is a sequence of character values including a zero-valued terminator. strlen returns the number of characters before the terminator:
/**
* A naive implementation of strlen. Actual implementations
* are a little more clever.
*/
size_t strlen( const char *str )
{
size_t count = 0;
while( str[count] )
count++;
return count;
}
The important thing to remember is that strlen returns the length of the string, not the size of the array containing the string. If you have something like
char foo[1024] = “bar”;
the strlen( foo ); returns 3.
If you tried to pass an integer or floating point array to strlen the compiler would yell at you because of the wrong argument type. You could work around this by casting the argument to char *, but you would still likely get a wrong answer, not only because integer and float types are multiple chars wide, but also because such a value may have an embedded zero-valued byte. For example, the integer value 16 is represented as the bytes 0x00, 0x00, 0x00, 0x10. If that’s the first element of your integer array, then strlen would return 0 on a big-endian platform and 1 on a little-endian platform.
If you defined the array, then you know how big it is. If you’re writing a function that receives an array argument, then you must either also receive the size as a separate argument, or you must rely on the presence of a sentinel value in the array.
Just do this to get the length of your float array,
int main()
{
float ar[4] = {1.1,1.2,1.3,1.4};
float b;
printf("Array Size : %d\n",sizeof(ar)/sizeof(b));
return 0;
}
You'll get the total number of element of your array , which you can use further in a loop to print the elements of array.
Note: Do not Use sizeof in case of pointers.
strlen() takes a "const char *" type value as argument. So it cannot be used with integer or float arrays.
I have to find the largest product of 13 adjacent numbers of a 1000-digit number below. My code for the problem is as follows:
#include <stdio.h>
int main()
{
char arr[1000] =
"731671765313306249192251196744265747423553491949349698352031277450"
"632623957831801698480186947885184385861560789112949495459501737958"
"331952853208805511125406987471585238630507156932909632952274430435"
"576689664895044524452316173185640309871112172238311362229893423380"
"308135336276614282806444486645238749303589072962904915604407723907"
"138105158593079608667017242712188399879790879227492190169972088809"
"377665727333001053367881220235421809751254540594752243525849077116"
"705560136048395864467063244157221553975369781797784617406495514929"
"086256932197846862248283972241375657056057490261407972968652414535"
"100474821663704844031998900088952434506585412275886668811642717147"
"992444292823086346567481391912316282458617866458359124566529476545"
"682848912883142607690042242190226710556263211111093705442175069416"
"589604080719840385096245544436298123098787992724428490918884580156"
"166097919133875499200524063689912560717606058861164671094050775410"
"022569831552000559357297257163626956188267042825248360082325753042"
"0752963450";
int i, j;
long int max;
max = 0;
long int s = 1;
for (i = 0; i < 988; i++) {
int a = 0;
for (j = 1; j <= 13; j++) {
printf("%c", arr[i + a]);
s = s * arr[i + a];
a++;
}
printf("%c%d", '=', s);
printf("\n");
if (s > max) {
max = s;
}
}
printf("\nMaximum product is %d", max);
getchar();
}
Some outputs are zero even if none of the input is zero. The second output happens to be negative. The answers don't even match. Any help is appreciated.
Many set of 13 digits in your char array arr contains zeroes and that is why the multiplication of these sets will result in 0.
There are a couple of issues with your code:
You are using %d instead of %ld to print long int. Using the wrong conversion specifier will result in undefined behaviour.
If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
You are not converting the ASCII value of the digit into its actual value before multiplication. (ASCII value of '0' is 48). This results in integer overflow and is the cause for negative values to be printed.
So the statement:
s = s * arr[i + a];
should be changed to:
s = s * (arr[i + a] - '0');
You are also not resetting the product s to 1 at the beginning of the inner for loop and because of this, you end up multiplying values from the results of different sets of 13.
After making these changes, you can see the live demo here.
There are a few issues to tackle in this code:
Clean up spacing and variable names (an edit by another user helped resolve this issue). Remove redundant variables like a, which j could easily represent by iterating from 0 to 12 rather than 1 to 13. This seems cosmetic but will make it easier for you to understand your program state, so it's actually critical.
Numerical overflow: As with all PE problems, you'll be dealing with extremely large numbers which may overflow the capacity of the long int datatype (231 - 1). Use unsigned long long to store your max and s (which I'd call product) variables. Print the result with %llu.
Convert chars to ints: arr[i+j] - '0'; so that you're multiplying the actual numbers the chars represent rather than their ASCII values (which are 48 higher).
s (really product) is not reset on each iteration of the inner loop, so you're taking the product of the entire 1000-sized input (or trying to, until your ints start to overflow).
void shifttable(char p[]) {
int i, j, m;
m = strlen(p);
for (i = 0; i < MAX; i++)
t[i] = m;
for (j = 0; j < m - 1; j++)
t[p[j]] = m - 1 - j;
}
I think, t[p[j]]=m-1-j; part, is indexed using a character.
Can someone explain me how its actually working?
The array indexing operator is treated as *(arr + index).
When one operand of the binary + operator is a pointer, the other operand must be an integral type.
char is an integral type.
Hence,
t[p[j]] = m-1-j;
is a legal statement.
The character will be converted to equivalent ascii value and it acts as an index to an array. Below piece of code gives you an example,
void main()
{
int a[10];
a['\t'] = 10;
printf("%d\n",a[9]);
}
Output: 10
Here ascii value of tab is 9 so a[9] will be 10. Please refer https://www.asciitable.com/ for decimal and hex equivalent of character.
Hope it helps you.
p[j] returns the ascii code of j-th character in p[], which is used later as index in t (the ascii code is extended to int by the compiler, see integer promotions).
char is an integral type. It can be used as an index value for the [] operator. Note however that t['0'] is not the same element as t[0]. The value of '0' depends on the encoding used on the platform. Most environments use ASCII for the source and execution character sets, where '0' has the value 48.
Indexing through character values is useful for many algorithms, especially searching and word matching. Typical implementations of the functions in <ctype.h> use arrays of 257 entries (or sometimes 384 entries for safety) where the function argument is used as an index.
Yet there is a major problem in using char values an index variables: the char type can be signed or unsigned by default, so the range of its values can encompass negative values. In the code fragment, if t is an array or a pointer to the beginning of an array, any character in p with a negative value will cause an access outside the boundaries of the array, which has undefined behavior.
It is advisable to raise the warning level so the compiler diagnoses such uses that are well hidden potential bugs. Use gcc -Wall or clang -Weverything.
To avoid this potential problem, the code should be modified this way:
#define MAX 256
int t[MAX];
void shifttable(char p[]) {
int i, j, m;
m = strlen(p);
for (i = 0; i < MAX; i++)
t[i] = m;
for (j = 0; j < m - 1; j++)
t[(unsigned char)p[j]] = m - 1 - j;
}
Note also that i, j, m and the t array should have type size_t to handle strings longer than INT_MAX.
I'm working on my own printf code and I got 2 problems that I hoped you might be able to help me with.
The first one is with the %p option :
This option gives me the pointer address of a void* in hex form.
So what I'm doing is this :
void printp(void *thing)
{
dectohex((long)&thing, 1);
}
where dectohex is just a function converting a decimal to hex.
The result will always be correct, except for the last 3 characters. Always. For example :
me : 0x5903d8b8 , printf : 0x5903da28.
And these characters don't change very often, whereas the other part changes at each call like its supposed to.
The other problem I have is with the %O option. I can't manage to convert a signed int to an unsigned int. printf prints huge numbers for negative int's, and no casts seems to work since I wouldn't have the place to store it anyways.
EDIT:
Thanks sooo much for the answers, so apparently for the first problem i was just a little stupid. For the second question i'm gonna try the different solutions you gave me and update you if i manage to do it.
Again thanks so much for your time and patience, and sorry for the delay in my response, i checked the email alert for any answer but it doesn't work apparently.
REEDIT: After reading your answers to my second question more carefully, i think some of you think i asked about %o or %0. I was really talking about %O as in %lo i think. In the man it tells me "%O : The long int argument is converted to unsigned octal". My problem is before converting the long int to octal, i need to convert it to something unsigned.
If uintptr_t/intmax_t is defined (it is optional), convert the pointer to that integer type and then print.
Otherwise, if sizeof(uintmax_t) >= sizeof (void *) , convert to uintmax_t. uintmax_t is a required type, but may not be sufficiently large.
void printp(void *thing) {
uintptr_t j = (uintptr_t) thing;
char lst[(sizeof j * CHAR_BIT + 3)/ 4 + 1]; // Size needed to print in base 16
char *p = &lst[sizeof lst] - 1;
*p = '\0';
do {
p--;
*p = "0123456789ABCDEF"[j%16];
j /= 16;
} while (p > lst);
fputs(p, stdout);
}
The %O problem is likely a sign extension issue. (#mafso) Insure valuables used are unsigned, like unsigned and unsigned long. Without seeing the code difficult to know for sure.
About the first issue you're having, just to make sure, you want to print the address of thing (note that thing itself is a pointer) or the address of the origin of thing (the pointer to the pointer thing)?
You're currently printing the pointer to the pointer.
Change
dectohex((long)&thing, 1);
to
dectohex((long)thing, 1);
if that is the case.
About the %O problem, can you give a code example?
You need "unsigned long long" for your cast.
Pointers are unsigned, but long is signed.
The number of bits in any data type is implementation-dependent; however these days it is common for long and unsigned long to be 32 bits.
edit: to be more clear, you can't count on anything about the number of bits in C, C++ or Objective-C, it's always implementation-dependent. For example it was at one time common to have nine bit bytes and thirty-six bit words. That's why the Internet Protocols always specify "octets" - groups of eight bites - rather then "bytes".
That's one advantage of Java, in that the number of bits in each data type is strictly definited.
About your second question regarding zero-padding and negative integers, which seems entirely separate from the first question about hex output. You can handle negative numbers like this (although in 32-bit it does not work with the value -2147483648 which is 0x80000000).
#include <stdio.h>
#define MAXDIGITS 21
int printint(int value, int zeropad, int width)
{
int i, z, len = 0;
char strg [MAXDIGITS+1];
strg [MAXDIGITS] = 0;
if (value < 0) {
value = - value;
putchar ('-');
len = 1;
}
for (i=MAXDIGITS-1; i>=0; i--) {
strg [i] = '0' + value % 10;
if ((value /= 10) == 0)
break;
}
if (zeropad)
for (z=MAXDIGITS-i; z<width; z++) {
putchar ('0');
len++;
}
for (; i<MAXDIGITS; i++) {
putchar (strg [i]);
len++;
}
return len;
}
int main (int argc, char *argv[])
{
int num = 0, len;
if (argc > 1) {
sscanf (argv[1], "%d", &num);
// try the equivalent of printf("%4d, num);
len = printint (num, 0, 4);
printf (" length %d\n", len);
// try the equivalent of printf("%04d, num);
len = printint (num, 1, 4);
printf (" length %d\n", len);
}
return 0;
}
This program gives us the position of the odd numbers in a given integer, this program works well, but when I give him an integer in its numbers are greater than 10 -like 123456789123-, it doesn't work.
I do not know if is a problem of ram or algorithm ?
#include<stdio.h>
#include<stdlib.h>
main(){
int a,b;
int i = 0;
scanf("%d",&a);
while(a/10!=0){
b=a%10;
if(b%2!=0)
printf("\nodd number position: %d",i);
a=a/10;
i++;
}
if(a%2!=0)
printf("\nodd number position: %d",i);
system("pause");
}
The problem is one of processor (architecture) rather than RAM. On your platform the size of an int seems to be 32 bits which cannot hold a number as large as 123456789123. As Groo commented to Raon, you could use a string instead (if you don't plan to do any calculations on the number):
char a[1024] = {0}; /* should be plenty, but extend the array even more if needed */
fgets(a, sizeof a, stdin); /* fgets is recommended as it doesn't overflow */
int i, length = strlen(a);
for(i = 0; i < length; i++){
/* count your odd digits here
left as an exercise to the reader */
/* note that you must access the individual digits using a[i] */
}
Every data type is limited to specific range.for example char is limited to range -128 to 128. if you use the beyond this range. You might get unexpected results.
In your program if you give any number which is beyond the range of integer, then you will get unexpected results
if your int size is 4 byte/32-bit you can give input with in this range –2,147,483,648 to 2,147,483,647
if Your int size is 2 byte/16-bit you can give input with in this range –32,768 to 32,767
Check this Data Type Ranges.
And if you want to give large Numbers You can declare variable as long int/long long int
and don't forgot to change format specifier when using long int(%ld) and long long int(%lld)
You can also use string and check whether all characters are digits are not by using isdigit() function in ctype.h header and convert character digit into integer digit by substracting '0'(character zero). and check whether is that odd or not.
The problem is that 123456789123 exceed the storage limit for an integer data type,
try using a string to store the value and parse it, something like
#include<stdio.h>
int main(){
char a[] = "12345678912345678913246798";
int i = 0;
for (i=0; a[i] != '\0'; i++){
if ( a[i] % 2 != 0 ) printf("%c is odd\n", a[i]);
}
return 0;
}
#include<stdio.h>
void main() {
int i;
char s[256];
scanf("%s",s);
for( i=0; s[i]!=0; ++i ) {
/*int digit = s[i]-48;
if( digit%2==1 ) break;
- or even shorter: */
if( s[i]%2==1 ) break;
}
if( s[i]!=0 )
printf( "First odd digit position: %d", i );
else
printf( "All digits are even" );
}
Here is working sample: http://cfiddle.net/sempyi
I think this program will not give proper answer if you give more than 10 digits! please correct me if I am wrong.
The max Unsigned integer value is 4294967295 (in any 32 bit processor). if the given value is more than that then it will either limit to that max value or overflow will happen. So if you give a integer which is more than 4294967295 it will not work as it supposed to.
try printing the input. In that case you will know whether complete number is sent or Max number is sent to find the odd number's position.
One way to make it work is read the input number as array of characters and then try to figure out the odd number position.
Note: for signed integer maximum is 2147483647
123456789123 is 0x1CBE991A83
so if int is 32 bit, your number is truncated (to 3197704835 or 0xBE991A83).
Number you are giving input is greater than range of int. You need to change the data type Below link should help you.
http://www.tutorialspoint.com/ansi_c/c_basic_datatypes.htm
You need to choose a data type that matches the expected data range.
If you want your program to work for any number it is probably best to read the number one character at a time.
Code (not that in this code, position is counted with the most significant digit = 1, which is the other direction compared to your code):
int c;
unsigned long long pos = 0;
while (++pos) {
c = getc();
if (c < '0' || c > '9') break; // Not a digit
if ((c - '0')%2 != 0) {
printf("\nodd number position: %ulld", pos);
}
}
The code can handle numbers that have a ridiculus amount of digits. Eventually the pos variable will overflow, though.