Count and get integers from a string using C - c

I am self teaching C programming.
I am trying to count number of int present in given string which are separated by space.
exp:
input str = "1 2 11 84384 0 212"
output should be: 1, 2, 11, 84384, 0, 212
total int = 6
When I try. It gives me all the digits as output which make sense since I am not using a right approach here.
I know in python I can use str.split (" ") function which can do my job very quickly.
But I want to try something similar in C. Trying to create my own split method.
#include <stdio.h>
#include <string.h>
void count_get_ints(const char *data) {
int buf[10000];
int cnt = 0, j=0;
for (int i=0; i<strlen(data); i++) {
if (isspace(data[i] == false)
buf[j] = data[i]-'0';
j++;
}
printf("%d", j);
}
// when I check the buffer it includes all the digits of the numbers.
// i.e for my example.
// buf = {1,2,1,1,8,4,3,8,4,0,2,1,2}
// I want buf to be following
// buf = {1,2,11,84384,0,212}
I know this is not a right approach to solve this problem. One way to keep track of prev and dynamically create a memory using number of non space digits encountered.
But I am not sure if that approach helps.

You want to build your number incrementally until you hit a space, then put that into the array. You can do this by multiplying by 10 then adding the next digit each time.
void count_get_ints(const char *data) {
int buf[10000];
int j = 0;
int current_number = 0;
// Move this outside the loop to eliminate recalculating the length each time
int total_length = strlen(data);
for (int i=0; i <= total_length; i++) {
// Go up to 1 character past the length so you
// capture the last number as well
if (i == total_length || isspace(data[i])) {
// Save the number, and reset it
buf[j++] = current_number;
current_number = 0;
}
else {
current_number *= 10;
current_number += data[i] - '0';
}
}
}

I think strtok will provide a cleaner solution, unless you really want to iterate over every char in the string. It has been a while since I did C, so please excuse any errors in the code below, hopefully it will give you the right idea.
#include <stdio.h>
#include <stdlib.h>
int main() {
char str[19] = "1 2 11 84384 0 212";
const char s[2] = " ";
char *token;
int total;
total = 0;
token = strtok(str, s);
while (token != NULL) {
printf("%s\n", token);
total += atoi(token);
token = strtok(NULL, s);
}
printf("%d\n", total);
return 0;
}

You can check the ascii value of each character by doing c-'0'. If it's between [0,9], then it's an integer. By having a state variable, when you're inside an integer by checking if a given character is a number of space, you can keep track of the count by ignoring white space. Plus you don't need a buffer, what happens if data is larger than 10,000, and you write pass the end of the buffer?, undefined behavior will happen. This solution doesn't require a buffer.
Edit, the solution now prints the integers that are in the string
void count_get_ints(const char *data) {
int count = 0;
int state = 0;
int start = 0;
int end = 0;
for(int i = 0; i<strlen(data); i++){
int ascii = data[i]-'0';
if(ascii >= 0 && ascii <= 9){
if(state == 0){
start = i;
}
state = 1;
}else{
//Detected a whitespace
if(state == 1){
count++;
state = 0;
end = i;
//Print the integer from the start to end spot in data
for(int j = start; j<end; j++){
printf("%c",data[j]);
}
printf(" ");
}
}
}
//Check end
if(state == 1){
count++;
for(int j = start; j<strlen(data); j++){
printf("%c",data[j]);
}
printf(" ");
}
printf("Number of integers %d\n",count);
}

I believe the standard way of doing this would be using sscanf using the %n format specifier to keep track of how much of the string is read.
You can start with a large array to read into -
int array[100];
Then you can keep reading integers from the string till you can't read anymore or you are done reading 100.
int total = 0;
int cont = 0;
int ret = 1;
while(ret == 1 && total < 100) {
ret = sscanf(input, "%d%n", &array[total++], &cont);
input += cont;
}
total--;
printf("Total read = %d\n", total);
and array contains all the numbers read.
Here is the DEMO

Example using strtol
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>
int count_get_ints(int output[], int output_size, const char *input) {
const char *p = input;
int cnt;
for(cnt = 0; cnt < output_size && *p; ++cnt){
char *endp;
long n;
errno = 0;
n = strtol(p, &endp, 10);
if(errno == 0 && (isspace((unsigned char)*endp) || !*endp) && INT_MIN <= n && n <= INT_MAX){
output[cnt] = n;
while(isspace((unsigned char)*endp))
++endp;//skip spaces
p = endp;//next parse point
} else {
fprintf(stderr, "invalid input '%s' in %s\n", p, __func__);
break;
}
}
return cnt;
}
int main(void) {
const char *input = "1 2 11 84384 0 212";
int data[10000];
int n = sizeof(data)/sizeof(*data);//number of elements of data
n = count_get_ints(data, n, input);
for(int i = 0; i < n; ++i){
if(i)
printf(", ");
printf("%d", data[i]);
}
puts("");
}

Assuming you don't have any non-numbers in your string, you can just count the number of spaces + 1 to find the number of integers in the string like so in this pseudo code:
for(i = 0; i < length of string; i++) {
if (string x[i] == " ") {
Add y to the list of strings
string y = "";
counter++;
}
string y += string x[i]
}
numberOfIntegers = counter + 1;
Also, this reads the data between the white spaces. Keep in mind this is pseudo code, so the syntax is different.

Related

I want to output * as a number and repeat the output as many times as I have entered

I got a problem of completing the code below.
#include <stdio.h>
void triR(void)
{
int size, repeat;
scanf("%d %d", &size, &repeat);
printf("Hello world\n");
// ...
// Complete this function
// ...
printf("Bye world\n");
}
Example of function excution
The above three are the input values.
I think The first is the minimum size of the number (I do not know why it does not work if I do not enter 1), the middle is the maximum size of the number, and the last is the number of iterations of the input value.
After looking at the example, I created the following code
#include <stdio.h>
#include <stdlib.h>
void triR(void)
{
int size, repeat;
int num;
scanf("%d %d", &size, &repeat);
printf("Hello world\n");
for (int b = 0; b < size; ++b) //b = horizontal line, a = number
{
for (int a = 0; a <= b; ++a)
{
for (num = 1; num <= a; ++num) - failed sentences
{
printf("%d", num);
}
}
printf("\n");
}
for (int k = size; k > 0 ; --k) //k = horizontal line, i = number
{
for (int i = 1; i < k; ++i)
{
{
printf("*"); -Sentences that were successfully run using *
}
}
printf("n");
}
// for (int c =o; ) - sentences tried to make about repeating output value
printf("Bye world\n");
return 0;
}
I know my code looks a lot strange.
I didn't have the confidence to make that code in numbers, so I tried to make it * and convert it.
It succeeded in running by *, but it continues to fail in the part to execute by number.
There is no one to ask for help, but I am afraid that I will not be able to solve it even if I am alone in the weekend. I can not even convert numbers far repeated outputs. I would really appreciate it even if you could give me a hint.
The above code I created(Failed)
Code with *
I'd like to say that even though I managed an implementation, it is definitely neither efficient nor practical. I had to restrict your size variable to digits, as I used ASCII to convert the numbers into characters and couldn't use the itoa() function, since it's not standard.
#include <stdio.h>
#include <stdlib.h>
void triR(void) {
int size, repeat;
scanf("%d %d", &size,&repeat);
printf("Hello world\n");
// string size of n^2+2n-1
char* print_string = malloc((size*size+2*size-1)*sizeof(char));
unsigned int number = 1;
unsigned int incrementer = 1;
while (number < size) {
for (int i = 0; i < number; i++) {
*(print_string+i+incrementer-1) = 48+number;
}
incrementer+=number;
number++;
*(print_string+incrementer-1) = '\n';
incrementer++;
}
while (number > 0) {
for (int i = 0; i < number; i++) {
*(print_string+i+incrementer-1) = 48+number;
}
incrementer+=number;
number--;
*(print_string+incrementer-1) = '\n';
incrementer++;
}
for (int i = 0; i < repeat; i++) {
printf("%s\n", print_string);
}
printf("Bye world\n");
free(print_string);
}
I allocated a char* with the size of size^2+2size-1, as this is the size required for the newline and number characters.
The variables number and incrementer are unsigned and start at 1 as they don't need to go below 1.
I put two while loops with similar code blocks in them:
while (number < size) {
for (int i = 0; i < number; i++) {
*(print_string+i+incrementer-1) = 48+number;
}
incrementer+=number;
number++;
*(print_string+incrementer-1) = '\n';
incrementer++;
}
while (number > 0) {
for (int i = 0; i < number; i++) {
*(print_string+i+incrementer-1) = 48+number;
}
incrementer+=number;
number--;
*(print_string+incrementer-1) = '\n';
incrementer++;
}
The first loop goes up to the size and inserts the characters into the char* in their positions. When the number is done, it increments the incrementer and adds the newline character.
The second loop goes down in number, doing the same things but this time decrementing the number variable. These two variables start at 1, as that's the start of the "pyramid".
*(print_string+i+incrementer-1) = 48+number;
There is a restriction here, in that if you exceed the number 9 your output will print whatever the ASCII representation of 58 is, so if you want to go above 9, you need to change that.
The for loop just prints the final string "repeat" times as wanted. The newline in the printf() function is not necessary, as the final string contains a newline character at the end, I left it in though. The downside of this implementation is that you're using a char* rather than some other sophisticated method.
Dont forget to free the char* when you're done, and don't forget to add user input error-checking.
#include <stdio.h>
#include <stdlib.h>
void clear(FILE *stream)
{
int ch; // read characters from stream till EOF or a newline is reached:
while ((ch = fgetc(stream)) != EOF && ch != '\n');
}
int main(void)
{
int min, max, count;
while (scanf("%d %d %d", &min, &max, &count) != 3 || // repeat till all 3 fields read successfully and
!min || !max || !count || min > max) { // only accept positive numbers as input
fputs("Input error!\n\n", stderr); // and make sure that the max is greater than the min
clear(stdin); // remove everything from stdin before attempting another read for values
}
puts("Hello world\n");
for (int i = 0; i < count; ++i) { // output the triangle count times
for (int row = min; row <= max; ++row) { // count row from min to max
for (int n = min; n <= row; ++n) // print row (row-min) times
printf("%d ", row);
putchar('\n'); // add a newline after every row
}
for (int row = max - 1; row >= min; --row) { // count from max-1 to min
for (int n = min; n <= row; ++n) // same as above: print row (row-min) times
printf("%d ", row);
putchar('\n'); // add a newline after every row
}
putchar('\n'); // add a newline between repetitions
}
puts("Bye world\n");
}

String array prints out trash values

So I have an assignment where I should delete a character if it has duplicates in a string. Right now it does that but also prints out trash values at the end. Im not sure why it does that, so any help would be nice.
Also im not sure how I should print out the length of the new string.
This is my main.c file:
#include <stdio.h>
#include <string.h>
#include "functions.h"
int main() {
char string[256];
int length;
printf("Enter char array size of string(counting with backslash 0): \n");
/*
Example: The word aabc will get a size of 5.
a = 0
a = 1
b = 2
c = 3
/0 = 4
Total 5 slots to allocate */
scanf("%d", &length);
printf("Enter string you wish to remove duplicates from: \n");
for (int i = 0; i < length; i++)
{
scanf("%c", &string[i]);
}
deleteDuplicates(string, length);
//String output after removing duplicates. Prints out trash values!
for (int i = 0; i < length; i++) {
printf("%c", string[i]);
}
//Length of new string. The length is also wrong!
printf("\tLength: %d\n", length);
printf("\n\n");
getchar();
return 0;
}
The output from the printf("%c", string[i]); prints out trash values at the end of the string which is not correct.
The deleteDuplicates function looks like this in the functions.c file:
void deleteDuplicates(char string[], int length)
{
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length;)
{
if (string[j] == string[i])
{
for (int k = j; k < length; k++)
{
string[k] = string[k + 1];
}
length--;
}
else
{
j++;
}
}
}
}
There is a more efficent and secure way to do the exercise:
#include <stdio.h>
#include <string.h>
void deleteDuplicates(char string[], int *length)
{
int p = 1; //current
int f = 0; //flag found
for (int i = 1; i < *length; i++)
{
f = 0;
for (int j = 0; j < i; j++)
{
if (string[j] == string[i])
{
f = 1;
break;
}
}
if (!f)
string[p++] = string[i];
}
string[p] = '\0';
*length = p;
}
int main() {
char aux[100] = "asdñkzzcvjhasdkljjh";
int l = strlen(aux);
deleteDuplicates(aux, &l);
printf("result: %s -> %d", aux, l);
}
You can see the results here:
http://codepad.org/wECjIonL
Or even a more refined way can be found here:
http://codepad.org/BXksElIG
Functions in C are pass by value by default, not pass by reference. So your deleteDuplicates function is not modifying the length in your main function. If you modify your function to pass by reference, your length will be modified.
Here's an example using your code.
The function call would be:
deleteDuplicates(string, &length);
The function would be:
void deleteDuplicates(char string[], int *length)
{
for (int i = 0; i < *length; i++)
{
for (int j = i + 1; j < *length;)
{
if (string[j] == string[i])
{
for (int k = j; k < *length; k++)
{
string[k] = string[k + 1];
}
*length--;
}
else
{
j++;
}
}
}
}
You can achieve an O(n) solution by hashing the characters in an array.
However, the other answers posted will help you solve your current problem in your code. I decided to show you a more efficient way to do this.
You can create a hash array like this:
int hashing[256] = {0};
Which sets all the values to be 0 in the array. Then you can check if the slot has a 0, which means that the character has not been visited. Everytime 0 is found, add the character to the string, and mark that slot as 1. This guarantees that no duplicate characters can be added, as they are only added if a 0 is found.
This is a common algorithm that is used everywhere, and it will help make your code more efficient.
Also it is better to use fgets for reading input from user, instead of scanf().
Here is some modified code I wrote a while ago which shows this idea of hashing:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NUMCHAR 256
char *remove_dups(char *string);
int main(void) {
char string[NUMCHAR], temp;
char *result;
size_t len, i;
int ch;
printf("Enter char array size of string(counting with backslash 0): \n");
if (scanf("%zu", &len) != 1) {
printf("invalid length entered\n");
exit(EXIT_FAILURE);
}
ch = getchar();
while (ch != '\n' && ch != EOF);
if (len >= NUMCHAR) {
printf("Length specified is longer than buffer size of %d\n", NUMCHAR);
exit(EXIT_FAILURE);
}
printf("Enter string you wish to remove duplicates from: \n");
for (i = 0; i < len; i++) {
if (scanf("%c", &temp) != 1) {
printf("invalid character entered\n");
exit(EXIT_FAILURE);
}
if (isspace(temp)) {
break;
}
string[i] = temp;
}
string[i] = '\0';
printf("Original string: %s Length: %zu\n", string, strlen(string));
result = remove_dups(string);
printf("Duplicates removed: %s Length: %zu\n", result, strlen(result));
return 0;
}
char *remove_dups(char *str) {
int hash[NUMCHAR] = {0};
size_t count = 0, i;
char temp;
for (i = 0; str[i]; i++) {
temp = str[i];
if (hash[(unsigned char)temp] == 0) {
hash[(unsigned char)temp] = 1;
str[count++] = str[i];
}
}
str[count] = '\0';
return str;
}
Example input:
Enter char array size of string(counting with backslash 0):
20
Enter string you wish to remove duplicates from:
hellotherefriend
Output:
Original string: hellotherefriend Length: 16
Duplicates removed: helotrfind Length: 10

How to make int value to a string

I'm trying to turn an int into string. I did it so far by getting the int with scanf, and then split it according to it's digits, and then put every one of the digits inside int array. Then I want to put all the int arr values inside a string, where the sign + or - will be the first character. Here is my code:
#include <stdio.h>
#include <string.h>
#define LENGTH 50
int getLength(int num, int arr[]);
int main()
{
int num = 0, i = 0;
int arr[LENGTH] = {0};
char string[LENGTH] = {0};
printf("enter number: ");
scanf("%d", &num);
int sizeMe = getLength(num, arr);
string[2] = arr[2] + '0';
printf("length %d one of values: %c", sizeMe,string[2]);
for(i = 1; i < sizeMe + 1; i++);
{
string[i] = arr[sizeMe - i] + '0';
}
string[0] = '+';
string[sizeMe] = 0;
printf("string: %s", string);
}
int getLength(int num,int arr[])
{
int count = 0;
int i = 0, temp = 0;
while(num != 0)
{
temp = num%10;
num /= 10;
count++;
i++;
arr[i] = temp;
printf("index %d is %d\n",i,arr[i]);
}
return count;
}
The output of that program is just '+'. What did I do wrong here?
The problem that is causing your code not to work is that you have a semicolon after the for statement like this:
for(i = 1; i < sizeMe + 1; i++);
{
string[i] = arr[sizeMe - i] + '0';
}
That code would be equivalent to this:
for(i = 1; i < sizeMe + 1; i++){}
string[i] = arr[sizeMe - i] + '0';
So what's happening there is that only the last element of string is written in, the rest is left blank, which generates undefined behavior. To solve the problem, remove the semicolon. I also recommend putting the { at the end of the line of the for statement instead of on a new line since doing so would prevent you from making such mistakes. This is therefore the correct code, formatted in the way that I recommend formatting:
for(i = 1; i < sizeMe + 1; i++){
string[i] = arr[sizeMe - i + 1] + '0';
}
Note that you also forgot the +1 in arr[sizeMe - i + 1].
Although that was the error that made your code not work the way you wanted it to work, you've also made several other mistakes, which could potentially cause your program to crash.
First of all, in the for loop, you're not testing if i is greater than LENGTH. The problem with that is that if i is greater than LENGTH, string[i] will be outside of the array, which will cause buffer overflow and make your program crash. To solve this problem, add the following code inside your for loop:
if(i + 1 > LENGTH){
break;
}
The break statement will exit the for loop immediately. Note that we're testing if i + 1 is greater than LENGTH to leave space for the null character at the end of the string.
For the same reason, string[sizeMe] = 0; is also bad, since nothing says that sizeMe is less than the size of the array. Instead, use string[i] = 0;, since i has been incremented until it either reaches LENGTH or sizeMe. Therefore, i will be the minimum of these two values, which is what we want.
You also need to return something at the end of the main function. The main function is of type int, so it should return an int. In C++, this code wouldn't compile because of that. Your code compiled since you're using C and C compilers are generally more tolerant than C++ compilers, so you only got a warning. Make sure to fix all compiler warnings, since doing so can solve bugs. The warnings are there to help you, not to annoy you. Generally, the main function should return 0, since this value usually means that everything went well. So you need to add return 0; at the end of the main function.
Therefore, this is the code you should use:
#include <stdio.h>
#include <string.h>
#define LENGTH 50
int getLength(int num, int arr[]);
int main(){
int num = 0, i = 0;
int arr[LENGTH] = {0};
char string[LENGTH] = {0};
printf("enter number: ");
scanf("%d", &num);
int sizeMe = getLength(num, arr);
string[2] = arr[2] + '0';
printf("length %d one of values: %c", sizeMe,string[2]);
for(i = 1; i < sizeMe + 1; i++){
string[i] = arr[sizeMe - i + 1] + '0';
if(i + 1 > LENGTH){
break;
}
}
string[0] = '+';
string[i] = 0;
printf("string: %s", string);
return 0;
}
int getLength(int num,int arr[]){
int count = 0;
int i = 0, temp = 0;
while(num != 0){
temp = num%10;
num /= 10;
count++;
i++;
arr[i] = temp;
printf("index %d is %d\n",i,arr[i]);
}
return count;
}
Also, as some programmer dude pointed out in a comment, it's much easier to use sprintf. Then your code would be much simpler:
#include <stdio.h>
#include <string.h>
#define LENGTH 50
int main(){
int num = 0;
char string[LENGTH] = {0};
printf("enter number: ");
scanf("%d", &num);
sprintf(string, "%c%d", num >= 0 ? '+' : '-', num);
printf("string: %s", string);
return 0;
}
The short answer to turning a C int into a decimal string is to call sprintf(). That leads to the question how sprintf() does it.
From the book The C Programming Language, 2nd edition section 3.6. There is an example of a function that return a string representation of an integer. So here is the code:
void numberToString(int n, char *s){
int i, sign;
if ((sign = n) < 0) /*record sign*/
n = -n; /* make n positive */
i = 0;
do { // generate digits in reverse order
s[i++] = n % 10 + '0'; // get next digit*/
} while ((n /= 10) > 0); // delete it
s[i++] = sign < 0? '-': '+'; // or -- if(sign < 0) s[i++] = '-'; -- if you want just the sign '-'
s[i] = '\0';
strrev(s); //reverse the string
}
int main()
{
int n;
char str[LENGTH];
printf("Number: ");
scanf("%i", &n);
numberToString(n, str);
printf("Number as string: %s\n", str);
}
strrev is defined in the string.h header (so include it).
You can try and do this with sprintf. When you calculate the number length from get_length(), you can declare a string buffer, either statically or dynamically. Once declared, you can send the formatted output in the buffer with sprintf().
However, if you wish to still use your approach, #Donald Duck has covered the issues into debugging your code, and this is just another approach you can use if you want to.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
size_t get_length(int number);
int main(void) {
int number;
size_t numcnt;
char *string;
printf("Enter number: ");
if (scanf("%d", &number) != 1) {
printf("Invalid number entered\n");
exit(EXIT_FAILURE);
}
printf("Number = %d\n", number);
numcnt = get_length(number);
string = malloc(numcnt+1);
if (!string) {
printf("Cannot allocate %zu bytes for string\n", numcnt+1);
exit(EXIT_FAILURE);
}
sprintf(string, "%d", number);
printf("String = %s\n", string);
free(string);
return 0;
}
size_t get_length(int number) {
size_t count = 0;
if (number < 0) {
number *= -1;
count++;
}
for (size_t i = number; i > 0; i /= 10) {
count++;
}
return count;
}
Sample input 1:
Enter number: 1234
Sample output 1:
Number = 1234
String = 1234
Sample input 2:
Enter number: -1234
Sample output 2:
Number = -1234
String = -1234

scan n numbers without spaces in C

Suppose n numbers are to be input in a single line without any spaces given the condition that these numbers are subject to the condition that they lie between 1 and 10.
Say n is 6 , then let the input be like "239435"
then if I have an array in which I am storing these numbers then I should get
array[0]=2
array[1]=3
array[2]=9
array[3]=4
array[4]=3
I can get the above result by using array[0]=(input/10^n) and then the next digit
but is there a simpler way to do it?
Just subtract the ASCII code of 0 for each digit and you get the value of it.
char *s = "239435"
int l = strlen(s);
int *array = malloc(sizeof(int)*l);
int i;
for(i = 0; i < l; i++)
array[i] = s[i]-'0';
update
Assuming that 0 is not a valid input and only numbers between 1-10 are allowed:
char *s = "239435"
int l = strlen(s);
int *array = malloc(sizeof(int)*l);
int i = 0;
while(*s != 0)
{
if(!isdigit(*s))
{
// error, the user entered something else
}
int v = array[i] = *s -'0';
// If the digit is '0' it should have been '10' and the previous number
// has to be adjusted, as it would be '1'. The '0' characater is skipped.
if(v == 0)
{
if(i == 0)
{
// Error, first digit was '0'
}
// Check if an input was something like '23407'
if(array[i-1] != 1)
{
// Error, invalid number
}
array[i-1] = 10;
}
else
array[i] = v;
s++;
}
E.g.
int a[6];
printf(">");
scanf("%1d%1d%1d%1d%1d%1d", a,a+1,a+2,a+3,a+4,a+5);
printf("%d,%d,%d,%d,%d,%d\n", a[0],a[1],a[2],a[3],a[4],a[5]);
result:
>239435
2,3,9,4,3,5
You can use a string to take the input and then check each position and extact them and store in an array. You need to check for the numeric value in each location explicitly, as you are accepting the input as a string. For integers taken input as string, there's no gurantee that the input is pure numeric and if it is not, things can go wild.
check this code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char ipstring[64];
int arr[64];
int count, len = 0;
printf("Enter the numbersi[not more than 64 numbers]\n");
scanf("%s", ipstring);
len = strlen(ipstring);
for (count = 0; count < len ; count++)
{
if (('0'<= ipstring[count]) && (ipstring[count] <= '9'))
{
arr[count] = ipstring[count] - '0';
}
else
{
printf("Invalid input detectde in position %d of %s\n", count+1, ipstring );
exit(-1);
}
}
//display
for (count = 0; count < len ; count++)
{
printf("arr[%d] = %d\n", count, arr[count]);
}
return 0;
}

C - Find most frequent element in char array

i'm developing a little function to display the most frequent character in a (char) array.
This is what I've accomplished so far, but I think i'm on the wrong way.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char test[10] = "ciaociaoci";
max_caratt(test, 10);
}
int max_caratt(char input[], int size)
{
int i;
char max[300];
max[0] = input[0];
for (i=0; i<size; i++)
{
if(strncmp(input,input[i],1) == 1)
{
printf("occourrence found");
max[i] = input[i];
}
}
}
Any help?
Actually, the correct code is this.
It's just a corrected version of IntermediateHacker's below snippet.
void main()
{
int array[255] = {0}; // initialize all elements to 0
char str[] = "thequickbrownfoxjumpedoverthelazydog";
int i, max, index;
for(i = 0; str[i] != 0; i++)
{
++array[str[i]];
}
// Find the letter that was used the most
max = array[0];
index = 0;
for(i = 0; str[i] != 0; i++)
{
if( array[str[i]] > max)
{
max = array[str[i]];
index = i;
}
}
printf("The max character is: %c \n", str[index]);
}
The easiest way to find the most common character is to create an int array of 255 and just increment the arraly element that corresponds to the character. For example: if the charcter is 'A', then increment the 'A'th element (if you look at any ascii table you will see that the letter 'A' has a decimal value of 65)
int array[255] = {0}; // initialize all elements to 0
char str[] = "The quick brown fox jumped over the lazy dog.";
int i, max, index;
// Now count all the letters in the sentence
for(i = 0; str[i] != 0; i++)
{
++array[str[i]];
}
// Find the letter that was used the most
max = array[0];
index = 0;
for(i = 0; str[i] != 0; i++)
{
if( array[i] > max)
{
max = array[i];
index = i;
}
}
printf("The max character is: %c \n", (char)index);
You're passing a (almost) string and a char to strncmp(). strncmp() takes two strings (and an integer). Your program shouldn't even compile!
Suggestion: increase the warning level of your compiler and mind the warnings.
You may want to look at strchr() ...
Assuming an input array of 0-127, the following should get you the most common character in a single pass through the string. Note, if you want to worry about negative numbers, shift everything up by +127 as needed...
char mostCommonChar(char *str) {
/* we are making the assumption that the string passed in has values
* between 0 and 127.
*/
int cnt[128], max = 0;
char *idx = str;
/* clear counts */
memset((void *)cnt, 0, sizeof(int) * 128);
/* collect info */
while(*idx) {
cnt[*idx]++;
if(cnt[*idx] > cnt[max]) {
max = *idx;
}
idx++;
}
/* we know the max */
return max;
}
If you don't need to preserve the input array, you could sort the input array first, then find the longest contiguous run of a single character. This approach is slower, but uses less space.
I made a working version using structs. It works fine, I guess, but I think there's a MUCH better way to write this algorithm.
#include <stdio.h>
#include <stdlib.h>
struct alphabet {
char letter;
int times;
};
typedef struct alphabet Alphabet;
void main() {
char string[300];
gets(string);
Alphabet Alph[300];
int i=0, j=0;
while (i<=strlen(string)) {
while(j<=300) {
if(string[i] != Alph[j].letter) {
Alph[i].letter = string[i];
Alph[i].times = 1;
}
else {
Alph[j].times++;
}
j++;
}
j=0;
i++;
}
int y,max=0;
char letter_max[0];
for (y=0; y<strlen(string); y++) {
printf("Letter: %c, Times: %d \n", Alph[y].letter, Alph[y].times);
if(Alph[y].times>max) {
max=Alph[y].times;
letter_max[0]=Alph[y].letter;
}
}
printf("\n\n\t\tMost frequent letter: %c - %d times \n\n", letter_max[0], max);
}
I saw you all creating big arrays and "complex" stuff so here I have easy and simple code xD
char most_used_char (char s[]) {
int i; //array's index
int v; //auxiliary index for counting characters
char c_aux; //auxiliary character
int sum = 0; //auxiliary character's occurrence
char c_max; //most used character
int max = 0; //most used character's occurrence
for (i = 0; s[i]; i++) {
c_aux = s[i];
for (v = 0; s[v]; v++)
if (c_aux == s[v]) sum++; /* responsible cycle for counting
character occurrence */
if (sum > max) { //checks if new character is the most used
max = sum;
c_max = c_aux;
}
sum = 0; /* reset counting variable so it can counts new
characters occurrence */
}
return c_max; //this is the most used character!
}

Resources