integers displayed instead of a sorted string - c

i want to sort a string using counting sort but instead of a sorted string some integer values are displayed with a warning iteration 254u invokes undefined behavior pointing at the expression c[i]+=c[i-1] even though the iterations doesn't seem to exceed the signed int limit
the code is
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define range 255
void count_sort(char arr[],int n)
{
int c[range];
int i;
memset(c,0,sizeof(c));
char b[strlen(arr)];
for(i=0;i<n;i++)
{
++c[arr[i]];
}
for(i=1;i<=range;++i)
{
c[i]+=c[i-1];
}
for(i=n-1;i>=0;--i)
{
b[c[arr[i]]-1]=arr[i];
--c[arr[i]];
}
for(i=0;i<n;i++)
{
arr[i]=b[i];
}
}
void print(char arr[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%d ",arr[i]);
}
}
int main()
{
char arr[]="november";
int n=sizeof(arr)/sizeof(arr[0]);
count_sort(arr,n);
print(arr,n);
return 0;
}
what changes are required to make the code run correctly

I checked you here link. The code is correct except for the lines below
(1) printf("%d ",arr[i]);
Change this line to the following since you are printing characters and not integers.
printf("%c ",arr[i]);
If you keep %d then you are casting the char to an integer, and you'll get the ascii value. So for %d specifier, you will get a sorted array of integer values which are ascii values for the corresponding characters.
(2) int c[range];
Change the line to the following
int c[range+1];
Now in your second for loop, it will not exceed the bounds of the array c and you will not get the undefined behavior.
Hope this will help you.

Here are some points that I'd like to share:
You're using %d as format specifier in printf() in print function so change that to %c like this:
printf("%c ", arr[i]);
If your string is properly \0 terminated and you can do without printing space between characters then you can directly use printf() with %s it:
printf("%s", arr);
You don't need the custom print() function in this case.
This loop
for ( int i = 1; i <= range; ++i ) // <== out-of-bounds
{
c[i] += c[i-1];
}
is causing out-of-bounds access resulting in Undefined Behavior. As range represents 255 but the loop condition is i <= range whereas it should be i < range to keep the iterations in the valid range i.e. 0-254.
You are calculating the length of the string like this:
int n = sizeof(arr) / sizeof(arr[0]);
sizeof also calculates the terminating '\0' character so the length of the string will be:
sizeof( arr ) = 9
sizeof( arr[0] ) = 1
n = 9 / 1 = 9
But, the length of the string november is 8. strlen() would be a better choice here.
int n = strlen( arr );
Or,
int n = sizeof( arr ) - 1; // don't include `\0`
In the count_sort function, you're declaring the arrayc like this:
int c[range];
And, then using memset to set it. You could initialize it like this:
int c[range] = {0};
More on memset here.
The array b is declared like this:
char b[strlen(arr)];
^^^^^^^^^^^
But, you already have n, use that. You don't need to calculate the length again.

You should use %c instead of %d to print the characters.
You should also use for( i=1; i < range; i++ ), i <= range will give fault as last index of array is range-1.

there are some problem in you code first you are using wrong format specifier for printing chars.You have to use %c instead of %d in your printing function.
also you should remove = from this loop for(i=1;i<=range;++i) , otherwise you will pass boundaries of array c which will lead to undefined behavior , or if you need that element you should declare c[range+1] instead of c[range].
also note that in your sorting since ASCII code of \0 is smallest , it will become first element of your array and so neither b nor arr will be terminated.
I suggest this loop:
for (i = n - 2; i >= 0; --i)
{
b[c[arr[i]] - 2] = arr[i];
--c[arr[i]];
}
b[n-1] = '\0';

Related

Count occurrences of a string character in an array

int count(char letter, int* array, int number)
{
int sum= 0;
int i;
for(i = 0; i < number; ++i)
{
if(array[i] == letter)
++sum;
}
return sum;
}
int main(){
char array[] = { 'A','B','B','C'};
int number= sizeof(array) / sizeof(char);
count("A", array, number);
return 0;
}
I am attempting to count an occurrence of a particular character in an array and get nothing. The problem is certainly in the way I pass the character argument, but I struggle to find a similar example online.
I did a bit of tweaking of your code so that the parameters in your function align with the parameters passed when your function is called. Following is an example of what your code might look like in order to count characters.
#include <stdio.h>
#include <stdlib.h>
int count(char letter, char* array, int number) /* Made second parameter a character array in lieu of an integer array */
{
int sum= 0;
int i;
for(i = 0; i < number; ++i)
{
if(array[i] == letter)
++sum;
}
return sum;
}
int main()
{
char array[] = { 'A','B','B','C'};
int number= sizeof(array) / sizeof(char) ;
printf("Count: %d\n",count('A', array, number)); /* Changed from string constant "A" to character 'A' */
return 0;
}
First off, you appear to want to send a character as your first parameter to your function. In your original code you were actually sending a string constant as "A" was enclosed in double quotes and not single quotes. The second parameter is a character array (aka, a string). Therefore, in your function definition the second parameter there needs to be a character array and not an integer array. Characters take up one or two bytes of memory depending upon the system, and integers "usually" take up four bytes of memory. So there would be a mismatch in attempting to check out array values.
Using your revised function to produce output for a "printf" call, I received the following output on my terminal.
Count: 1
So probably the biggest takeaway from this is that characters (e.g. 'A') are different from string constants (e.g. "A"), and characters, even though they equate to an integer value, utilize a smaller chunk of memory than do integers.
Hope that helps.
Regards.

Getting different lengths for the same operation with different number values in C

I have 2 for-loops which populate arrays with letters from the alphabet. I have a lowercase array set, and an uppercase array set. The problem is when I initialize the arrays with the letters, the lengths are coming back different.
char uppercase[26];
char lowercase[26];
int indexUpper = 0;
int indexLower = 0;
// Get uppercase array:
for(int a = 65; a <= 90; a++){
uppercase[indexUpper] = a;
indexUpper++;
}
// Get lowercase array:
for(int b = 97; b <= 122; b++){
lowercase[indexLower] = b;
indexLower++;
}
printf("UPPERCASE = %lu\n", strlen(uppercase));
printf("LOWERCASE = %lu\n", strlen(lowercase));
$=> UPPERCASE = 26
$=> LOWERCASE = 27
I apologize if this is a no brainer. I am truly trying to learn and comprehend the C language and its rules. Thanks to all who contribute.
strlen() reads the character array as long until it finds a NUL byte ('\0', numerical value zero). Your arrays don't contain any, since you haven't assigned one there.
That means that strlen will continue reading past the end of the array, which is illegal, and the resulting behaviour is not defined. Getting a 27 is rather mild, you could be getting arbitrary numbers, or your program could crash.
If you want to use strlen(), you should explicitly assign a NUL byte at the end of the string, and of course allocate space for it.
Perhaps something like this:
#include <stdio.h>
#include <string.h>
int main(void)
{
char upper[27];
int i;
for (i = 0 ; i < 26; i++) {
/* This only works in a character set where the letters
are contiguous */
upper[i] = 'A' + i;
}
/* i == 26 now */
upper[i] = '\0';
printf("len: %u\n", (unsigned) strlen(upper));
return 0;
}
(Though using strlen here at all seems somewhat pointless, since you already know the number of items in those arrays.)
When using strlen the char array must be nul terminated - but yours isn't so you have undefined behavior.
To print the size of the arrays try:
printf("UPPERCASE = %zu\n", sizeof uppercase);
printf("LOWERCASE = %zu\n", sizeof lowercase);

Issues with creating a copy of an argument in C

I am converting string arguments into ints I am having an issue where the first argument is not copying and converting to a string while the second argument is working just fine. I am removing the first character of the string array and printing out the rest of the string as an int.
#include <stdio.h>
#include <string.h>
#include <math.h>
int main(int argc, char *argv[])
{
char numcpy1[sizeof(argv[1])-1];
char numcpy2[sizeof(argv[2])-1];
int i, len1, len2;
int result1=0;
int result2=0;
//Access first character for base
printf("%c \n", argv[2][0]);
printf("%c \n", argv[3][0]);
//Remove first character for number1 and number 2
if(strlen(argv[2]) > 0)
{
strcpy(numcpy1, &(argv[2][1]));
}
else
{
strcpy(numcpy1, argv[2]);
}
len1 = strlen(numcpy1);
if(strlen(argv[3]) > 0)
{
strcpy(numcpy2, &(argv[3][1]));
}
else
{
strcpy(numcpy2, argv[3]);
}
len2 = strlen(numcpy2);
//Turn remaining string characters into an int
for(i=0; i<len1; i++)
{
result1 = result1 * 10 + ( numcpy1[i] - '0' );
}
for(i=0; i<len2; i++)
{
result2 = result2 * 10 + ( numcpy2[i] - '0' );
}
printf("%d \n", result1);
printf("%d \n", result2);
return 0;
}
Output:
b
b
-4844
1010
What I want:
b
b
1000
1010
The sizeof operator does not give you the length of a string, as you seem to think it does. It tell you the size of the datatype. Since argv[2] is a char *, this evaluates to the size of this pointer, most likely 4 or 8 depending on the system.
If the string in question is longer than this value, you end up writing past the end of the array. This invokes undefined behavior, which in your case manifests as an unexpected result.
If you want the length of the string, use the strlen function instead. Also, you need to add one more byte. Strings in C are null terminated, so you need space for the null byte that marks the end of the string.
char numcpy1[strlen(argv[2])];
char numcpy2[strlen(argv[3])];
Also note that we don't need to add 1 to each of these since the first character in each string isn't copied.
You need to change
char numcpy1[sizeof(argv[1])-1];
to
char numcpy1[strlen(argv[1]) + 1];
Ditto for numcpy2
I think instead of copying the numbers you could work more easily with pointers. Thereby, you don't have to think about memory allocation and copying the values just for the sake of converting them into an integer value:
const char *numcpy1 = argv[2][0]=='\0' ? argv[2] : argv[2]+1;
...

index out of bounds when accessing last item in array

I have a random number generator feeding numbers into an array, but when I print out the table, the last line is always a set of values out of the boundaries that I defined in the following function:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int temp[22];
int n;
for(n=0; n<23; n++){
temp[n] = rand()%(100 + 1 - 60) + 60;
printf("%d , %d \n", n, temp[n]);
}
return 0;
Ive created something of this nature before, but now its acting up, I just dont know where.
You are accessing the array outside the bounds which is undefined behaviour.
Instead make use of sizeof operator to avoid such problems:
for(n = 0; n < sizeof temp/sizeof temp[0]; n++)
But note that if temp were to be an malloc'ed pointer (int *temp = malloc(23 * sizeof *temp);) then sizeof wouldn't work.
Your array is being accessed outside of its bounds.
int temp[22];
This declaration assigns 22 indices to temp, temp[0] is the first
value and temp[21] is the last value you can access in your array. Counting 0, from 0..21 = we have 22 values
Your for loop is incorrect:
for(n=0; n<23; n++)
This will make the program attempt to access temp[22], which doesn't exist. You need to change it to:
for(n=0; n<22; n++)
Furthermore:
return 0; needs to be inside and at the end of your main() function. It's possibly a typo, but you're missing a closing brace } in your main() function, at least how you posted it.

Garbage characters in string

I've written code to make a right pyramid out a character.
However, when I execute the program, the last two lines of the pyramid have garbage characters placed after them even when it exceeds the size of the array.
The code is here:
#include <stdio.h>
#include <string.h>
#define ROW 5
int main(void) {
char array[ROW];
int x = 0;
int row = 0;
for (row = 0; row < ROW; row++) {
array[x] = 'a';
if (x < ROW) {
printf("%s\n", dolla);
}
x++;
}
getchar();
}
Where are the garbage characters coming from? It's only on lines after the third.
The problem in your code is that you have not terminated your string with \0 (null) character. Here's a workout for your code:
#include <stdio.h>
#include <string.h>
#define ROW 5
int main(void)
{
char array[ROW];
int x = 0;
int row = 0;
for(row = 0; row < ROW; row++)
{
array[x] = 'a';
if(x < ROW)
{
array[x+1]='\0';
printf("%s\n", array);
}
x++;
}
getchar();
}
I'm no specialist, but I've read the following in many typical C books:
int arrays in C are initialized to 0, while char arrays are initialized to garbage.
And yeah, forgot to mention, it's no dolla, it's array.
char array[ROW+1] = {0}; will help you a lot. You might have assumed array was empty but it was full of random characters. By initializing with {0}, the array starts with all zeroes.
I'm going to assume dolla was a transcription error and that either dolla should be array or that array used to be named dolla.
You are probably exceeding the values in the array to make the pyramid which results in printing out garbage values that were there before you even compiled your code.
When you print the values, rather than printing out whole array ( which means there can be garbage values included ) you can print up to the point where you have valid values and this can be done by introducing a null character '\0' at the end of the array.
Also initializing you array would be a better choice here as then you can debug your code better after seeing the output.

Resources