I want split the following string into alphabet and numbers, then I need to calculate the sum of the numbers. My sample question is a[20]={"abcd123dc2"};
Expected output:
abcddc 8
My code:
int main()
{
char a[20] = {"abcd123dc2"};
int l = 0, m = 0, n = 0, j, cc = 0, ll = 0;
char b[20];
char c[10];
l = strlen(a);
printf("%d", l);
for (j = 0; j < l; j++)
{
if (a[j] == 'a' || a[j] == 'b' || a[j] == 'd' || a[j] == 'c')
{
b[m] = a[j];
m++;
}
}
b[m] = '\0';
for (j = 0; j < l; j++)
{
if (a[j] == '3' || a[j] == '2' || a[j] == '1')
{
c[n] = a[j];
n++;
}
}
ll = strlen(c);
atoi(c);
for (j = 0; j < ll; j++)
{
cc += c[j];
}
printf("%d\n\n", cc);
printf("%s", b);
getch();
return 0;
}
char a[20]={"abd123vf"};
int l=0,m=0,j,cc=0;
char b[20];
l=strlen(a);
for(j=0;j<l;j++)
{
if(a[j]> 47 && a[j] <58){
cc+ = a[j] - '0';
}
else{
b[m]=a[j];
m++;
}
}
b[m]='\0';
printf("%d\n\n",cc);
printf("%s",b);
getch();
return 0;
Edit after the first comment:
Since you have not specifically mentioned a problem, I assume you are looking for a better way of writing this code.
Instead of looping through your string twice, you can do it in a single go.
Instead of checking for individual numbers or letters, you can check if the character is in the range : 48 - 57 [i.e., 0 to 9]
Instead of two if conditions, you can go for an else.
[Note that even the special characters in the original string will be part of your new string in this case]
a[j] - '0' will give the actual number in the string. eg:
if the number is 5, a[j] will be 53;
'0' is 48; 53 - 48 = 5 and that's what you add to your sum
Your code is OK for the most part.
There is one error in computing c. Instead of
cc += c[j]; // The integer value of c[j] when it is `0` is 48, not 0
You need to use
cc += c[j] - '0';
Based on your expected output at the top of the question, your printf lines
printf("%d\n\n",cc);
printf("%s",b);
need to be
printf("%s %d\n",b,cc);
Other
You have an unnecessary call to atoi. Was that just for debugging?
I wouldn't do it this way, the algorithm is actually quite simple. Works for every string.
char a[] = "abcd123dc2";
char b[20];
char c[20];
int i, spotinnumbers = 0, spotincharacters = 0;
for(i = 0 ; i < strlen(a) ; i++)
{
if((a[i] >= 'a' && a[i] <= 'z') || (a[i] >= 'A' && a[i] <= 'Z'))
{
b[spotincharacters] = a[i];
spotincharacters++;
}
else if(a[i] >= '0' && a[i] <= '9')
{
c[spotinnumbers] = a[i];
spotinnumbers++;
}
}
b[spotincharacters] = '\0';
c[spotinnumbers] = '\0';
Some explanation of the code. Basically, it's not splitting, just having another two strings, one of the alphabet in the main string and one of the numbers in it. We use one loop to run on the string and decide whether the character is an alphabet letter or a number and assign it in the right place.
About the sum calculation... As we have the numbers in c:
int total = 0;
for(i = 0 ; i < strlen(c) ; i++)
{
total += c[i]-'0';
}
explanation about this piece of code, in this code, as a string in C is simply an array of characters, in the string we have the characters resembling the numbers but the characters' value in numeric is something called ASCII value. You can look at the ASCII Table and find out that each character has a numeric value and there's an overall of 256 characters (2^8) which is why a character takes one byte (1 byte = 8 bits = 2^8 possibilities for different numbers). '0''s ASCII is 48 and that's how we basically turn a number from a character to its true numeric value. for 0 (48-48 = 0) and for 1 (49-48 = 1) as all number characters in the ASCII table are in a series.
The actual problem in the code isn't just efficiency as there is no need to run in two loops and so, you enter the numeric values of the numbers into C ! which turns them to different characters.
Related
so this is my function. My main focus is to get the character frequencies and the highest character frequency.
The function below (get_letter_frequencies) is supposed to get a string example ("I am a big boy") and return the character frequencies and the highest character frequency.
The Function should return
i - 2
a - 2
m - 1
b - 2
g - 1
o - 1
y - 1
Highest character frequency would be " iab "
My problem is with the get_letter_frequencies function. What should I arrange from the function in order to return the above output?
void get_letter_frequencies(const char *text, size_t len, int freq[26], int *max_freq)
{
for(int i = 0; i<len; i++)
{
if(text[i] != ' ' || !(is_sentence_terminator(text[i]))) //this condition is set in order to ignore the spaces and the sentence terminators (! ? .)
{
if(text[i] >= 'a' && text[i] <= 'z')
{
freq[text[i] - 'a']++;
}
}
}
for(int j = 0; j < 26; j++)
{
if(freq[j] >= 1)
{
*max_freq = freq[j];
}
}
This function below(is_sentence_terminator). Here the function checks whether the sentence finishes with a " ! ? or . " if it does not finish with one of the terminators then it is not a sentence and ignores it.
int is_sentence_terminator(char ch)
{
if(ch == 33 || ch == 46 || ch == 63)
{
return 1;
}else
{
return 0;
}
}
There are some issues in your code:
there is no need to test for special characters, comparing text[i] to 'a' and 'z' is sufficient for ASCII systems.
in the second loop, you should update *max_freq only if freq[j] is greater than the current value, not 1. *max_freq should be initialized to 0 before the loop.
In the calling code, you would also
print the letters whose frequency is non 0.
print all letters with the maximum frequency using one final loop.
Here is a modified version:
void get_letter_frequencies(const char *text, size_t len, int freq[26], int *max_freq) {
for (int i = 0; i < 26; i++)
freq[i] = 0;
for (int i = 0; i < len; i++) {
if (text[i] >= 'a' && text[i] <= 'z') {
freq[text[i] - 'a']++; // assuming ASCII
}
}
*max_freq = 0;
for (int i = 0; i < 26; i++) {
if (*max_freq < freq[i]) {
*max_freq = freq[i];
}
}
}
I am trying to create a function that scans the user input and shows the counted integer numbers and add them. For example the user input would be 'room 2301 next to 12 street' the function would count the number 2301 as one, and 12 as two and add them, 2313 which is the sum and returns it. so the return would be count=2, sum= 2313. However, I am having an issue with the logic behind the function. Currently my function takes the numbers separately, eg. 2302 = 2,3,0,2.
Here is my code:
void num_count(char array[]) {
int i = 0;
int count = 0;
int sum = 0;
int tmp[20];
tmp_size = 20;
while (array[i] != '\0') {
if (array[i] >= '0' && array[i] <= '9') {
tmp[i] = (array[i] - '0');
//not sure what to do here
count++;
sum += (array[i] - '0');
}
i++;
}
}
currently I try to put it into a temp array but not really sure what to do next. Any help would be appreciated .
I think you should begin from the end of the array to the beginning.
When you encounter a digit you have to sum this first digit, then iterate the next character and if it is a digit you have to sum digit x10, the next one: digit x100...
When the next character is not a digit, reset the multiplier and count++.
if(isDigit){
sum+= digit*multiplier;
multiplier*=10;
}
else {
multiplier=1;
}
I don't inlcude the count part.
Use the following code snippet to extract the individual words of the string, check if the extracted word is a number, and, if a number, calculate the sum and increase the count.
int i;
int j;
int count;
int sum;
char *chars;
char *pChar;
int len;
int isNum;
for (i=0, count=0, sum=0; i<strlen(array);) {
pChar = strchr(array[i], ' ');
len = pChar - array[i];
chars = malloc(sizeof(char) * (len + 1));
strncpy(chars, array[i], len);
chars[len] = '\0';
for (j =0, isNum = 1; j<len; j++) {
if (!isdigit(chars[j])) {
isNum=0;
break;
}
}
if (isNum) {
count++;
sum += atoi(chars);
}
free(chars);
if (strchr(array[pChar - array + 1] != NULL)
i = (pChar - array) + 1;
else
break;
}
If you only need the sum, you do not have to save it as char in a char array (in your code it is named tmp[]), but you can directly convert it to integer (assuming no overflow will occur).
Every time you detect the first numeric character, you should reset the tmp to zero and continue multiplying by 10 before adding the next numeric value, until you detect a non-numeric character.
edit: I think the function should return the sum. So, you'd better change the function decoration as well (and add a return sum line).
int num_count(char array[]) {
int i = 0;
int sum = 0;
int tmp;
while (array[i] != '\0') {
if (array[i] >= '0' && array[i] <= '9') {
tmp = 0;
while (array[i] >= '0' && array[i] <= '9') {
tmp = tmp * 10 + array[i] - '0';
i++;
}
sum += tmp;
}
else {
i++;
}
}
return sum;
}
My program should first read an entered string word and then count the amount of repeated letters.
For example, if I enter apple it should print 1, but instead it prints 4.
I suppose word[i] = word[i + 1] isn't the right way to count?
#include<stdio.h>
int main() {
int i, j, wordLength = 0, alphabeticalSort, counter = 0, swap;
char word[51];
scanf("%s", word);
while (word[wordLength] != '\0'){
wordLength++;
}
...
for (i = 0; i < wordLength; i++){
if (word[i] = word[i + 1])
counter++;
}
printf("\nNumber of repeated letters: %d", counter);
...
return 0;
}
It's best to split what you're doing into two functions, one of which will count the number of occurrences of each letter.
#define LETTERS 26
/* counts number of occurrences of each lowercase letter in str. Result is placed in outCounts,
assuming it has room */
void countletters(char *str, int outCounts[])
{
memset(outCounts, 0, LETTERS * sizeof (int));
for (; *str; ++str) {
if (isupper(*str))
*str = tolower(str);
if (islower(*str))
++outCounts[*str - 'a'];
}
}
Then you write another function will examines the outCounts array, which is modified. If a letter is repeated, the corresponding member of this array will be greater than one. I leave this as an exercise to the reader.
You have:
for (i = 0; i < wordLength; i++){
if (word[i] = word[i + 1])
counter++;
}
Look at the 'comparison' inside the loop; you're giving the value of word[i+1] to word[i+1]. This condition will always be true unless the word[i+1]'s value is a 0 or a null char which is also a 0 in the ASCII table.
Remember: the equality operator in C is always ==, so replace the = with ==.
int main()
{
char string[80];
int c = 0, count[26] = {0}, x;
printf("Enter a string\n");
//gets(string);
scanf("%s", string);
while (string[c] != '\0') {
if (string[c] >= 'a' && string[c] <= 'z') {
x = string[c] - 'a';
count[x]++;
}
c++;
}
for (c = 0; c < 26; c++)
printf("%c occurs %d times in the string.\n", c + 'a', count[c]);
return 0;
}
I want to check if every character in word A is also in word B.
This function doesn't work yet, but I hope you can help me anyway.
I created a check variable which only increases if the character at the position i in word A is equal to the character i in word B.
int is_equal(char *a, char *b)
{
int i = 0, j;
int check = 0;
while (a[i] != '\0')
{
for (j = 0; b[j] != '\0'; j++)
{
if (a[i] == b[j]) //Here
{
i = i + 1;
j = 0;
check = check + 1; //Increase
}
else
{
i = i + 1;
j = 0;
}
}
}
if (check % strlen(a) == 0)
{
return 1;
}
return 0;
}
In the end of this function I'm gonna check if check % length of string a is 0.
And if that's the case, every character in A is also in B.
But it doesn't work because if a[i] and b[j] aren't equal, j is going to be reset to 0 and it crashes. So, how can I fix this? How can I reset the loop to check from the beginning?
The problem with your code is that you make a decision on whether or not a character from a[] matches anything form b[] inside the nested loop. This is too early for that decision, because your code did not have an opportunity to check other characters in b[].
You can modify your code to introduce a found flag, set it to zero before going into the nested loop, and then setting it to 1 if you find a match:
int found = 0;
for (j = 0 ; !found && b[j] != '\0' ; j++) {
found = a[i] == b[j];
}
The value of found after the loop indicates if any of the characters in b[] match a[i].
Note: This works well for short a[]s and b[]s, but for very long strings it could be too slow. A better approach is to walk b[] once, mark all chars in it, and then walk a[] to check if any characters are missing:
int seen[256] = {0};
for (int i = 0 ; b[i] ; i++) {
// Mark characters from b[]
seen[(unsigned char)b[i]] = 1;
}
for (int i = 0 ; a[i] ; i++) {
// Found a char in a[] that's not in b[]
if (!seen[(unsigned char)a[i]]) {
return 0;
}
}
return 1;
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Pseudocode explanation of what I am attempting to do.
Convert a character array into an integer array
Iterate through each integer in that array and add q to it, unless that integer + q exceeds an upper bound. If it exceeds that number, return the modulus and add the modulus to a lower bound.
print the converted integer array in its ASCII sequence using %c.
Here is the example:
int main(void)
{
char char_message[] = "abcyzABCYZ";
int q = 10;
int i;
int message[10];
int n = strlen(char_message);
for(i = 0; i < n; i++) {
message[i] = atoi(&char_message[i]);
}
for(i = 0; i < n; i++) {
if(message[i] <= 90) {
if (message[i] + q <= 90) {
message[i] = message[i] + q;
}
else
message[i] = 65 + (message[i] % 90);
}
else if(message[i] >= 97) {
if (message[i] + q <= 122) {
message[i] = message[i] + q;
}
else
message[i] = 97 + (message[i] % 122);
}
}
for(i = 0; i < n; i++) {
printf("%c", message[i]);
}
return 0;
}
EDIT: Below is a second attempt at this problem --------------------------
int main(int argc, char *argv[]) {
if(argc != 3) {
printf("Enter an integer followed by a string \n\n");
return 1;
}
int i;
int offset = atoi(argv[1]);
char **p_message;
p_message = &argv[2];
char encrypt[strlen(*p_message)];
printf("You Entered: %d, %s \n", offset, *p_message);
for(i = 0; i < strlen(*p_message); i++)
{
encrypt[i] = ((*p_message[i] + offset) % 26);
}
for(i = 0; i < strlen(*p_message); i++)
{
printf("%c", encrypt[i]);
}
return 0;
}
I'm not doing your homework for you, but it is obvious that two things are clearly wrong.
Your use of atoi is incorrect. It should not be here at all.
Your calculation of the resulting enciphered character is wrong as well. The modulus placement is wrong in two different locations.
Your use of "magic numbers" in this code is rampant making it much, much more difficult to read than need-be. Avoid using magic numbers.
The following "enciphers" your test string via a simple forward scanning loop, output each resulting character one at a time. I've left the storage to a separate int array for you to handle. Of note the first if-block is expanded out statement by statement so you can see what is going on one step at a time. The second (lower case handling) is done in a single expression. Other than different ranges, the two methods of calculation are equivalent.
Note: this only works on platforms where character ranges A..Z and a..z are continuous. The language standard makes no enforcement of this; it only enforces it for digit characters 0..9. Thus, don't blame me if you run this on an AS/400 or OS/390 (both EBCDIC platforms) and it doesn't work.
#include <stdio.h>
#include <string.h>
int main()
{
char message[] = "abcyzABCYZ";
const int q = 10;
puts(message);
for(const char *p = message; *p; ++p)
{
int c = (unsigned char)*p;
if (c >= 'A' && c <= 'Z')
{
c -= 'A';
c += q;
c %= ('Z' - 'A' + 1);
c += 'A';
}
else if (c >= 'a' && c <= 'z')
c = ((c - ('a' - q)) % ('z' - 'a' + 1)) + 'a';
// else nothing. keep as-is
fputc(c, stdout);
}
fputc('\n', stdout);
return 0;
}
Output
abcyzABCYZ
klmijKLMIJ