Count occurrences of a string character in an array - c

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.

Related

integers displayed instead of a sorted string

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';

segmentation fault in c while coding Vigenère’s cipher

I am really new to coding and I have been teaching myself how to code by using EDX.org. This week I have been studying about Cryptography and I have to create a Vigenère’s cipher. I wrote the code and for the most part, it's correct. However when I compiled the program, it's showing a segmentation error. I have been trying to figure our why this is happening and I am totally stuck. Could you take a look at my code and tell me whats wrong?
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int index(int k, int c);
int main (int argc, string argv[1])
{
//check for correct criteria
if (argc = 2, isalpha(argv[1]))
{
string text = GetString();
string key = argv[1]; //store key word
int Totalshift = strlen(key); //number of shift for keyword
int shift = 0;
//loops over the whole text
for (int i = 0, n = strlen(text); i <n; i++ )
{
char p= text[i];
char k = toupper(key[shift]); //Upper case for each character
if (isupper(p))
{
//convert to 0 index
p = p - 65;
k = k - 65;
int crypt= index (k , p);
printf("%c", crypt+65);
shift= (shift+1) %Totalshift;
}
else if (islower(p))
{
p = p - 97;
k = k - 65;
int crypt= index (k , p);
printf("%c", crypt+97);
shift= (shift+1) %Totalshift;
}
else
{
printf("%c", p);
}
}
printf("\n");
}
//error message
else
{
printf("ERROR!\n");
return 1;
}
}
//index function
int index(int k, int p)
{
return (k+p)% 26;
}
string
No. Never, ever hide pointers.
int main(int argc, char ** argv)
Then:
//check for correct criteria
if (argc = 2, isalpha(argv[1]))
Here, you assign to the variable (parameters behave like local variables in that respect) the value 2, thus destroying the previous value (which holds the number of arguments given to the program). The result is the value which was assigned, thus 2. Then, there's the comma operator: You discard that 2, and then call isalpha(argv[1]), which clearly shows why you should always turn on warnings and never, ever hide pointers:
argv[1] is of type char *, thus a pointer to a character array (or, as we know in this case, a character array terminated with '\0', which is called a C string). Since isalpha takes an int as parameter the value of the pointer ("the memory address") is implicitly converted to (a probably very large) int value. Quoting from above link, emphasis mine:
The c argument is an int, the value of which the application shall ensure is representable as an unsigned char or equal to the value of the macro EOF. If the argument has any other value, the behavior is undefined.
Which is possibly the source of the segmentation fault.
Finally, that GetString really looks fishy to me. Assuming that it allocates some memory (for the string that it presumably reads from the user) ... where do you free that memory? Is it really allocating memory, or possibly returning a pointer to an array with automatic storage duration (a local variable, so to say)?

shifting array element one by one

I got a homework question. I'm so close to complete program. I'm having trouble about one thing. This is the question:
Write a C program that generates and displays a character array of size 10 consisting of
random English lower-case letters. The program then asks the user how many times the array
will be right-shifted and displays the right shifted array at each right-shifting step. A sample
program execution output is given below. ( Hint: Use the ASCII codes of the English lower-case
letters which are 97, 98, ... 122 for a, b, ..., z, respectively, to generate the character array).
This is my code:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
void print_string (char *string){
int i;
for (i=0 ; i < 10 ; i ++){
printf("%c ", string[i]);
if (i == 9)
printf("\n");
}
}
void random_string(char *string, unsigned length)
{
/* Seed number for rand() */
srand((unsigned int) time(0) + getpid());
/* ASCII characters 97 to 122 */
int i;
for (i = 0; i < length; ++i)
{
string[i] = (rand() % 26)+ 97;
}
string[i] = '\0';
}
void reverse_string(char* str, int left, int right) {
char* p1 = str + left;
char* p2 = str + right;
while (p1 < p2) {
char temp = *p1;
*p1 = *p2;
*p2 = temp;
p1++;
p2--;
}
}
void rotate(char* str, int k, int n) {
reverse_string(str, 0, n-1);
reverse_string(str, 0, k-1);
reverse_string(str, k, n-1);
}
int main(void)
{
char s[11];
int i,shiftNum;
random_string(s, 11);
printf("Randomly constructed array is :\n");
print_string(s);
printf("Enter how many times array will be shifted: ");
scanf("%d",&shiftNum);
rotate(s,shiftNum,11);
print_string(s);
}
What's wrong with this code? When I execute it with 1, I couldn't get the first reverse correctly and I want to display all shifting steps.
For a start, it is atrocious that your lecturer/professor is telling you to use 97..122. C does not require that ASCII be the character set on every system, so this code is entirely non-portable, yet if you look at the history as far as Unix is concerned C is supposed to be a portable programming language. If you want to write this in a portable way, you need to store the characters in an array and select from that array:
char lowercase[] = "abcdefghijklmnopqrstuvwxyz";
string[i] = lowercase[rand() % (sizeof lowercase - 1)];
Now that we've covered that pedantic detail, Cool Guy indicated in a comment that this line of code is erroneous: string[i] = '\0';. He's correct about that.
This should also performed within main, not within random_string: srand((unsigned int) time(0) + getpid());. The reason is that calling random_string multiple times in the same second would result in the same "random string", which is very uncool.
scanf("%d",&shiftNum); can't guarantee success (that the user will input numeric data), and so can't guarantee that shiftNum will contain a sane value. You need to check the return value. For example:
if (scanf("%d", &shiftNum) != 1) {
puts("Invalid shift count!\n");
exit(0);
}
You should probably also consider using an unsigned type for shiftNum (and this will cause the corresponding format spec %d to change to something else, such as %u for unsigned int).
One more important task before I finish this task: You need to modify rotate to handle an input of 0 correctly, since some users might want to rotate/shift 0 times (as an alternative to not rotating/shifting at all). I'm confident that this should be an easy task for you.

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.

Finding the length of a Character Array in C

What is a way in C that someone could find the length of a character array?
I will happily accept pseudo-code, but am not averse to someone writing it out if they'd like to :)
Provided the char array is null terminated,
char chararray[10] = { 0 };
size_t len = strlen(chararray);
If you have an array, then you can find the number of elements in the array by dividing the size of the array in bytes by the size of each element in bytes:
char x[10];
int elements_in_x = sizeof(x) / sizeof(x[0]);
For the specific case of char, since sizeof(char) == 1, sizeof(x) will yield the same result.
If you only have a pointer to an array, then there's no way to find the number of elements in the pointed-to array. You have to keep track of that yourself. For example, given:
char x[10];
char* pointer_to_x = x;
there is no way to tell from just pointer_to_x that it points to an array of 10 elements. You have to keep track of that information yourself.
There are numerous ways to do that: you can either store the number of elements in a variable or you can encode the contents of the array such that you can get its size somehow by analyzing its contents (this is effectively what null-terminated strings do: they place a '\0' character at the end of the string so that you know when the string ends).
Although the earlier answers are OK, here's my contribution.
//returns the size of a character array using a pointer to the first element of the character array
int size(char *ptr)
{
//variable used to access the subsequent array elements.
int offset = 0;
//variable that counts the number of elements in your array
int count = 0;
//While loop that tests whether the end of the array has been reached
while (*(ptr + offset) != '\0')
{
//increment the count variable
++count;
//advance to the next element of the array
++offset;
}
//return the size of the array
return count;
}
In your main function, you call the size function by passing the address of the first element of your array.
For example:
char myArray[] = {'h', 'e', 'l', 'l', 'o'};
printf("The size of my character array is: %d\n", size(&myArray[0]));
You can use strlen
strlen(urarray);
You can code it yourself so you understand how it works
size_t my_strlen(const char *str)
{
size_t i;
for (i = 0; str[i]; i++);
return i;
}
if you want the size of the array then you use sizeof
char urarray[255];
printf("%zu", sizeof(urarray));
If you want the length of the character array use sizeof(array)/sizeof(array[0]), if you want the length of the string use strlen(array).
There is also a compact form for that, if you do not want to rely on strlen. Assuming that the character array you are considering is "msg":
unsigned int len=0;
while(*(msg+len) ) len++;
using sizeof()
char h[] = "hello";
printf("%d\n",sizeof(h)-1); //Output = 5
using string.h
#include <string.h>
char h[] = "hello";
printf("%d\n",strlen(h)); //Output = 5
using function (strlen implementation)
int strsize(const char* str);
int main(){
char h[] = "hello";
printf("%d\n",strsize(h)); //Output = 5
return 0;
}
int strsize(const char* str){
return (*str) ? strsize(++str) + 1 : 0;
}
You can use this function:
int arraySize(char array[])
{
int cont = 0;
for (int i = 0; array[i] != 0; i++)
cont++;
return cont;
}
By saying "Character array" you mean a string? Like "hello" or "hahaha this is a string of characters"..
Anyway, use strlen(). Read a bit about it, there's plenty of info about it, like here.
Well, 11 years later, I run into this issue with a college assignment. The solution I found, worked without having to alter the function signatures that the assignment was asking for.
In my case, I had to make a function that returns the item index if the item existed or depending on if the itemPrefix (e.g. 'B' for Banana) already exists or not in the character array itemPrefixes to avoid passing duplicate prefixes.
So, I had to use a for loop (or while loop). The problem was that the assignment had given me specific signatures for each function and for that specific function it didn't allow me to pass the count variable that was on the main() function as an argument.
I had to improvise.
Both the ways mentioned above didn't work. strlen() didn't work as intended since there was not a '\0' end character that strings have. The sizeof() method also didn't work, because it returned the size of the pointer of the character array that was passed in as an argument instead of the number of elements.
So, this is the function I came up with. A simple while loop that checks whether the current character is NULL (or 0).
void charArrLength(char array[]) {
int arrLength = 0;
while (array[arrLength] != 0) {
arrLength++; //increment by 1
}
printf("Character array has %d elements", arrLength);
}
For this to work though, in the main() function, you need to declare your character array as a character pointer and then allocate the memory that you need based on the number of items that you ultimately wish to have inside your array.
void charArrLength(char array[]) {
int arrLength = 0;
while (array[arrLength] != 0) {
arrLength++;
}
printf("Character array has %d elements", arrLength); //should give 33
}
int main() {
char *array; //declare array as a pointer
int arraySize = 33; //can be anything
array = (char*) malloc(arraySize * sizeof(char));
charArrLength(array);
free(array); //free the previously allocated memory
}
Below you will see how I utilised this function in my assignment.
First, here is the above function tailored to my needs.
int isItemExists(char itemPrefixes[], char itemPrefix) {
int count = 0; //declare count variable and set to 0
int itemIndex = -1; //declare item index variable and set it to -1 as default
while (itemPrefixes[count] != 0) {
count++;
}
for (int i = 0; i < count; i++) {
if (itemPrefix == itemPrefixes[i]) {
itemIndex = i; //if item exists, set item index to i
}
}
return itemIndex;
}
Then, how I declared the itemPrefixes array in main() function and how I allocated the needed memory based on n (the number of items the user would like to add to itemPrefixes array).
char *itemPrefixes;
int n = 0; //number of items to be added variable
printf("> Enter how many items to add: ");
scanf("%d", &n);
//allocate n * size of char data type bytes of memory
itemPrefixes = (char*) malloc(n * sizeof(char));
And finally, here is how that function was used after all.
do {
printf("\n\n> Enter prefix for item %d: ", i + 1);
scanf(" %c", &itemPrefix);
//prompt the user if that itemPrefix already exists
if (isItemExists(itemPrefixes, itemPrefix) != -1) {
printf("\nItem prefix already exists! Try another one.\n");
}
} while (isItemExists(itemPrefixes, itemPrefix) != -1);
Also, in the end of the code I free the previously allocated memory.
free(itemPrefixes);
To clear this out, again, this could be much easier if the conditions were different. The assignment was strict about not passing n as an argument. Nevertheless, I hope I help someone else that might be looking for this in the future!
Just for the sake of it, if anybody sees this and has something simpler to suggest, feel free to tell me.

Resources