I'm very new to C and trying to create a counter for how many times the letter "a" appears in a string. I get it working by putting it directly into main, however when I put it into a function, my printf outputs 0.
#include <stdio.h>
#include <string.h>
#define STRING_LENGTH 50
void letter_counter(char input[STRING_LENGTH], int count, char letter ) {
int i;
for (i = 0; i < strlen(input); i++){
if (input[i] == letter) {
count++;
}
}
}
int main() {
int a1 = 0;
char a = 'a';
printf("Please write a word\n");
char input[STRING_LENGTH] = {0};
fgets(input,STRING_LENGTH,stdin);
input[strlen(input) - 1] = 0;
letter_counter(input, a1, a);
printf("%i\n", a1);
}
You are not returning the value of what you have counted. It looks like you think that a1 is going to contain the total, but it's not.
Your letter_counter function needs to return an int value, not void.
int letter_counter(char input[STRING_LENGTH], char letter ) {
int i;
int count = 0;
for (i = 0; i < strlen(input); i++){
if (input[i] == letter) {
count++;
}
return count;
}
Then you need to assign the return value of the function to a variable:
a1 = letter_counter(input, a);
Related
My goal is to write a function, that calculates the number of all the unique characters from a redirected text file (meaning until EOF is reached). The code I wrote:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ASCII_VALS 128
int strLen (char inp[])
{
int len = 0;
for(int i = 0; inp[i] != '\0'; i++){
len++;
}
return len;
}
int countUniqueChars (char inp[])
{
int everyCharValArr[ASCII_VALS] = {0};
int i, j = 0;
for(i = 0; i < strLen(inp); i++){
int convToInt = inp[i] - '0';
everyCharValArr[convToInt] = 1;
}
for (i = 0; i < ASCII_VALS; i++) {
j += everyCharValArr[i];
}
return j;
}
works for one string entered via scanf() like so:
int main ()
{
char inp[100];
printf("Enter a string: \n");
scanf("%99s", inp);
printf("%d\n", countUniqueChars(inp));
return 0;
}
But after I change the main function to read a redirected text file, like so:
int main ()
{
char inp[100];
int total = 0;
while(fgets(inp, 100, stdin)){
total += countUniqueChars(inp);
}
printf("%d\n", total);
return 0;
}
and runinng the program (./binary <input.txt) on a input.txt file with contents below:
Toydolls
Flies
trees
rocks
things
the value becomes 26, which is correct (1. word = 6 unique chars, 2. word = 5 unique chars, 3. word = 4 unique chars, 4. word = 5, 5. word = 6 unique chars), but it obviously does not take into consideration chars that appear on more lines, which should not be counted as unique chars at all. My question is How do I fix the function to accomplish this?
Try something like that: Note that I've added a mechanism not to count a duplicate uppercase letter and its lower case letter as unique.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#define ASCII_VALS 128
int everyCharValArr[ASCII_VALS] = {0};
int strLen (char inp[])
{
int len = 0;
for(int i = 0; inp[i] != '\0'; i++){
len++;
}
return len;
}
void FindUniqueChars (char inp[])
{
int i;
for(i = 0; i < strLen(inp); i++){
if (inp[i] > ' ' && inp[i] != (char)127)
{
if (inp[i] >= 'A' && inp[i] <='Z')
{
inp[i] = tolower(inp[i]);
}
everyCharValArr[(int)inp[i]] = 1;
}
}
}
int CountUniqueChars( void )
{
int i, j = 0;
for (i = 0; i < ASCII_VALS; i++) {
j += everyCharValArr[i];
}
return j;
}
int main ()
{
char inp[100];
while(fgets(inp, 100, stdin)){
FindUniqueChars(inp);
}
printf("%d\n", CountUniqueChars());
return 0;
}
I want to make A to 1, ... , Z to 26.
My code can make A to 1, but it can't make J -> 10 , ... , Z -> 26. Please tell me how to change mine.
void changeToDigitEncode(char s[], char e[]) {
int i;
int eIndex = 0;
for (i = 0; s[i] != '\0'; i++) {
e[eIndex] = s[i]-'A'+'0'+1;
eIndex++;
}
e[eIndex] = '\0';
}
int main(void) {
char sentence[20], encoded[40];
scanf("%s", sentence);
changeToDigitEncode(sentence, encoded);
printf("%s\n", encoded);
}
Normally you can do this:
int a_lower = 'a' - 'a' + 1; // value : 1
int j_lower = 'j' - 'a' + 1; // value : 10
For capitals, a similar thing:
int a_upper = 'A' - 'A' + 1; // value : 1
int j_upper = 'J' - 'A' + 1; // value : 10
As a comment pointed out, You can't store most integers as a single character. Whereas a character array element is a single character. So, instead you will have to create an integer array and store the values there.
Plus, it would be s[i]-'A'+ 1 simply
Another thing I added is a termination condition for the encoded array which would be number 0 as no alphabet will give number 0.
#include <stdio.h>
void changeToDigitEncode(char s[], int e[]) {
int i;
int eIndex = 0;
for (i = 0; s[i] != '\0'; i++) {
e[eIndex] = s[i]-'A'+1;
eIndex++;
}
e[eIndex] = 0;
}
int main(void) {
char sentence[20];
int encoded[20];
scanf("%s", sentence);
changeToDigitEncode(sentence, encoded);
for(int i=0; encoded[i]!=0; i++) {
printf("%d ",encoded[i]);
}
}
try this code consider ip[] as your s[] and op[] as your e[]
char ip[] = "ABC";
char op[3];
char temp[50];
int i=0;
int j=0;
int k=0;
while(ip[i]!='\0')
{
int num=ip[i];
num-=64;
sprintf(temp, "%d", num);
k=0;
while(temp[k]!='\0')
{
op[j++]=temp[k++];
}
i++;
}
op[i]='\0';
printf("-->%s\n",op);
this will only work for String in Caps
As the title says %s is not working properly This is for a code wars so %s needs to be able to work with the array to pass the sample test cases; Cannot change function declaration of playPass. Using Ascii table. Also the for loop to print in main() works and gives me correct output.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// takes a string and shifts letter n value;
// lower cases every other element if it contains a letter
// replaces number with a 9 complement
// returns array with values reversed.
char* playPass(char* s, int n)
{
int length = strlen(s);
char *pass= (char *)malloc(length*sizeof(char)+1);
char a;
int letter, i;
for(i=0; i< length; i++)
{
a = s[i];
letter = a;
if( letter >= 65 && letter <=90 )
{
letter +=n;
if(letter >90)
{
letter -=90;
letter +=64;
}
if((i+1) % 2 == 0 )
{
letter += 32;
}
a = letter;
}
else if(letter >= 48 && letter <= 57)
{
letter -= 48;
letter = 9 - letter;
a = letter + '0';
}
pass[length - i] = a;
}
return pass;
}
// answer should be
int main (){
char* s ={"I LOVE YOU!!!"};
int length = strlen(s);
int k = 1;
s =playPass( s,k );
int i;
printf(" %s", s);
for(i = 0; i <= length; i++)
{
printf(" %c", s[i]);
}
}
%s works only with null terminated char *
char* playPass(char* s, int n) {
…
for() {
…
}
pass[i] = '\0'; //Null terminate here.
return pass;
}
so figured it out.
the end where i assined the new value to the new array
pass[length - i] = a;
made it to where it never wrote a value to the first element so
pass[0]= NULL;
had to change it to
pass[length - (i-1)] = a;
thanks for the help everyone, I also cleaned up the code from the magic numbers Great tip #phuclv!
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
I am having an issue with this program, I want it to only displays words in the input once and count each time they appear, however it is displaying every word entered.
for example if i enter
"this should only only appear appear once"
then i want the program to output
this 1
should 1
only 2
appear 2
once 1
Any help would be appreciated.
#include <stdio.h>
#include <string.h>
#define ROW 1000
#define COL 50
int read_input(char *str, int n);
int main(void)
{
char str[ROW];
char stringSeperate[ROW][COL] = { };
const char *s= " ,.!";
char *p;
int freq[ROW];
int i = 0;
int wordCount = 0;
int pos = 0;
read_input(str, ROW);
p = strtok(str,s);
i = 1;
while(p !=NULL) {
wordCount = i;
for(i = 0; i < wordCount; i++) {
if (strcmp(p, stringSeperate[i]) != 0)
pos = 1;
else
pos = i;
}
if (pos == 1) {
strcpy(stringSeperate[i], p);
freq[i++]++;
}
else
freq[pos]++;
p = strtok(NULL,s);
}
for ( i = 1; i <= wordCount; i++ ) {
printf("Word: %s\t Number: %d\n",stringSeperate[i], freq[i]);
}
return 0;
}
int read_input(char *str, int n)
{
int ch, i = 0;
while((ch = getchar()) != '\n') {
if ( i < n ) {
*str++ = ch;
i++;
}
}
*str = '\0';
return i;
}
You invoked undefined behavior by using value of uninitialized variable freq having automatic storage duration, which is indeterminate.
Initialize it like int freq[ROW] = {0};
Also you should
1. Change initialization of stringSeperate to standard: empty initlalizer is not allowed, so it should be like
char stringSeperate[ROW][COL] = {{0}};
2. Remove extra printing to match the desired output: change
printf("Word: %s\t Number: %d\n",stringSeperate[i], freq[i]);
to
printf("%s %d\n",stringSeperate[i], freq[i]);
3. Check the length of input in order not to cause buffer overrun. Change
if ( i < n ) {
in read_input to
if ( i < n - 1 ) {
in order to make room for terminating null-characteer.