separate numbers and string into text and numbers - c

I am trying to write code where I can separate string and numbers.
The string I have to separate it completely already the numbers I have to separate every 2 numbers.
My Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void getString(const char *str) {
char nums[50];
char alphas[50];
for (int i = 0; i < strlen(str); i++) {
if (isdigit(str[i]))
strcpy(nums, str);
if (isalpha(str[i]))
strcpy(alphas, str);
}
printf("str: %s\n", alphas);
printf("num: %d\n", atoi(nums));
}
int main() {
char *str = "one01two02three03";
getString(str);
return 0;
}
What I'm trying to do should return me as follows
str: onetwothree
num1: 01
num2: 02
num3: 03

The following parses the input and produces the correct output.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int *nums = NULL;
int num_count = 0;
char save_num(int n)
{
nums = realloc(nums, sizeof(int)*(num_count+1));
nums[num_count++] = n;
return '\0';
}
void getString(const char *str)
{
char* alpha = malloc(strlen(str)+1);
char* num = malloc(strlen(str)+1);
size_t i;
alpha[0] = '\0';
num[0] = '\0';
for (i = 0; i < strlen(str); i++)
{
if (isdigit(str[i]))
strncat(num, str+i, 1);
else if(isalpha(str[i]))
{
strncat(alpha, str+i, 1);
if(strlen(num) > 0)
num[0] = save_num(atoi(num));
}
}
if(strlen(num) > 0)
save_num(atoi(num));
printf("str: %s\n", alpha);
for(i = 0 ; i < num_count ; ++i)
printf("num%Zu: %02d\n", i+1, nums[i]);
free(alpha);
free(num);
}
int main()
{
char *str = "one01two02three03";
getString(str);
return 0;
}

This provides what you have asked for:
void getString(const char *str)
{
char one[10],two[10],three[10];
int x,y,z;
char a[10],b[10],c[10];
sscanf(str,"%[^0-9]""%[0-9]""%[^0-9]""%[0-9]""%[^0-9]""%[0-9]",a,one,b,two,c,three);
x = atoi(one);
y = atoi(two);
z = atoi(three);
printf("str: %s%s%s\n",a,b,c);
printf("num: %d\n",x);
printf("num: %d\n",y);
printf("num: %d\n",z);
}
DonĀ“t forget to provide the declaration of getString before main():
void getString(const char *str);
So all together:
#include <stdio.h>
void getString(const char *str);
int main()
{
char *str = "one01two02three03";
getString(str);
return 0;
}
void getString(const char *str)
{
char one[10],two[10],three[10];
int x,y,z;
char a[10],b[10],c[10];
sscanf(str,"%[^0-9]""%[0-9]""%[^0-9]""%[0-9]""%[^0-9]""%[0-9]",a,one,b,two,c,three);
x = atoi(one);
y = atoi(two);
z = atoi(three);
printf("str: %s%s%s\n",a,b,c);
printf("num: %d\n",x);
printf("num: %d\n",y);
printf("num: %d\n",z);
}
Output:
str: onetwothree
num: 01
num: 02
num: 03

Since you have already set your strings 'nums' and 'alphas' there is no need to handle them dynamically.You should just copy the elements of the array str,one by one, to either the array num or the array alphas.
To distinguish different numbers just put a special character between numbers in the num array.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void getString(const char *str)
{
char nums[50];
char alphas[50];
int digits = 0;
int alpha = 0;
for (int i = 0; i < strlen(str); i++) {
if (isdigit(str[i])){
while(isdigit(str[i])){
nums[digits] = str[i];
i++;
digits++;
}
nums[digits]='\n';
digits++;
}
if(isalpha(str[i])){
alphas[alpha] = str[i];
alpha++;
}
}
printf("str: %s\n", alphas);
int n,p=0;
char subbuf[5];
for(n=0;n<digits;n++){
p=n;
while(nums[n]!='\n'){
n++;
}
memcpy(subbuf,&nums[p],n-p);
printf("num: %d\n", atoi(subbuf));
}
}
int main()
{
char *str = "01two02three03";
getString(str);
return 0;
}
Be aware that strcpy sets the pointer of the first argument to point to the second argument,this means that when you write strcpy(nums,str) in your code above, you copy the entire str string to the num several times.

Using an array for this question is not necessary, unless the array is to be used later. So my answer to this question is short and simple:
#include <stdio.h>
#include <stdbool.h>
void getString(const char *str)
{
bool in_number = false;
while (*str) {
if (*str >= '0' && *str <= '9') {
if (!in_number) { // Transition from a non-digit to digit
printf(": ");
in_number = true;
}
} else if (in_number) { // Transition from a digit to non-digit
putchar('\n');
in_number = false;
}
putchar(*str++);
}
putchar('\n');
}
int main(void)
{
char *str = "one01two02three03";
getString(str);
return 0;
}
The boolean variable in_number is used to catch the transitions from a digit character to a non-digit character and from a non-digit character to a digit character.

Related

Need to sort a string input by the most frequent characters first in C (qsort)

I managed to sort it alphabetically but I need to sort it by the most frequent characters first after that. Since I'm new to C programming Im not sure if this alphabetical sort is needed. Also I thought about using a struct but not sure how to do the whole process with it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmpfunc(const void *a, const void *b) {
return *(char*)a - *(char*)b;
}
void AlphabetOrder(char str[]) {
qsort(str, (size_t) strlen(str), (size_t) sizeof(char), cmpfunc);
printf("%s\n", str);
}
void Max_Occurring(char *str)
{
int i;
int max = 0;
int freq[256] = {0};
for(i = 0; str[i] != '\0'; i++)
{
freq[str[i]] = freq[str[i]] + 1;
}
for(i = 0; i < 256; i++)
{
if(freq[i] > freq[max])
{
max = i;
}
}
printf("Character '%c' appears %d times", max, freq[max], str);
}
int main() {
char str1[20];
printf("Enter a string: ");
scanf("%s", &str1);
AlphabetOrder(str1);
Max_Occurring(str1);
return 0;
}
I wrote you a frequency sorter using the idea that #WeatherVane mentioned:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct cfreq {
unsigned char c;
int freq;
};
int freqcmp(const void *a, const void *b) {
struct cfreq *a2 = (struct cfreq *) a;
struct cfreq *b2 = (struct cfreq *) b;
if(a2->freq < b2->freq) return -1;
if(a2->freq == b2->freq) return 0;
return 1;
}
int freqcmpdesc(const void *a, const void *b) {
return -freqcmp(a, b);
}
void FrequencyOrder(const char str[]) {
struct cfreq cfreqs[256];
for(int i = 0; i < sizeof(cfreqs) / sizeof(*cfreqs); i++) {
cfreqs[i].c = i;
cfreqs[i].freq = 0;
}
for(int i = 0; str[i]; i++) cfreqs[str[i]].freq++;
qsort(cfreqs, sizeof(cfreqs) / sizeof(*cfreqs), sizeof(*cfreqs), freqcmpdesc);
for(int i = 0; i < sizeof(cfreqs) / sizeof(*cfreqs); i++) {
if(cfreqs[i].freq) printf("%c", cfreqs[i].c);
}
printf("\n");
}
int main() {
char str1[20];
printf("Enter a string: ");
scanf("%s", &str1);
FrequencyOrder(str1);
return 0;
}
and here is a sample session (note: output is not deterministic for letters with same frequency):
Enter a string: buzz
zbu
If you want duplicate letters in the output then replace the print with a loop along these lines:
while(cfreqs[i].freq--) printf("%c", cfreqs[i].c);
Im not sure if this alphabetical sort is needed.
It is not needed, yet if done, Max_Occurring() can take advantage of a sorted string.
Since the string is sorted before calling Max_Occurring(), compute the max occurring via a count of adjacent repetitions of each char.
// Untested illustrative code.
// str points to a sorted string.
void Max_Occurring(const char *str) {
char max_ch = '\0';
size_t max_occurence = 0;
char previous = '\0';
size_t occurrence = 0;
while (*str) {
if (*str == previous) {
occurrence++;
} else {
occurrence = 1;
}
if (occurrence > max_occurence) {
max_occurence = occurrence;
max_ch = *str;
}
previous = *str;
str++;
}
printf("Character '%c' appears %zu times", max_ch, max_occurence);
}
In the case of multiple characters with the same max occurrence, this code only reports one max.
Avoid buffer overflow
Do not use scanf("%s"... without a width limit.
Tip: enable all warnings to save time and see the problem of using &str1 when str1 should be used.
char str1[20];
...
// scanf("%s", &str1);
scanf("%19s", str1);
Avoid a negative index
If still wanting to for a frequency table, watch out for the case when char is signed and code use str[i] < 0 to index an array.
Instead:
const unsigned char *ustr = (const unsigned char *) str;
size_t freq[UCHAR_MAX + 1] = {0};
for(size_t i = 0; ustr[i] != '\0'; i++) {
freq[ustr[i]]++;
}
Here's another alternative that may be simpler.
void freqOrder( char *p ) {
#define ASCIIcnt 128 // 7bit ASCII
// to count occurences of each character
int occur[ ASCIIcnt ];
memset( occur, 0, sizeof occur );
int maxCnt = 0; // remember the highest count
// do the counting
for( ; *p; p++ )
if( ++occur[ *p ] > maxCnt )
maxCnt = occur[ *p ];
// output most frequent to least frequen
for( ; maxCnt; maxCnt-- )
for( int i = 0; i < ASCIIcnt; i++ )
if( occur[i] == maxCnt )
while( occur[i]-- )
putchar( i );
putchar( '\n' );
}
int main( void ) {
freqOrder( "The quick brown fox jumps over the lazy dog" );
return 0;
}
Output
' ooooeeehhrruuTabcdfgijklmnpqstvwxyz'

How to make characters appear in the correct order in C?

I have a C program which is meant to return the repeating characters and their frequencies from a given input string. At the moment, it works fine, however I was wondering if there was a way I could change it so it would return characters in order of appearance, as opposed to alphabetical(?) order.
# include <stdio.h>
# include <stdlib.h>
#include <ctype.h>
# define NO_OF_CHARS 256
char fillCharCounts(unsigned char *str, int *count)
{
int i;
for (i = 0; *(str+i); i++)
count[*(str+i)]++;
return 0;
}
void printDups(unsigned char *str)
{
int *count = (int *)calloc(NO_OF_CHARS,
sizeof(int));
fillCharCounts(str, count);
int dupe_chars = 0;
int i;
for (i = 0; i < NO_OF_CHARS; i++)
if (count[i] > 1) {
printf ("\nDuplicate letter: %c, Occurrences: %d", i, count[i]);
++dupe_chars;
}
if (0 != dupe_chars)
printf ("\n");
else
printf ("\nNo duplicates found\n");
free(count);
}
int main()
{
unsigned char str[15] = "";
printf("Enter a word>");
scanf("%s", str);
printDups(str);
getchar();
return 0;
}
At the moment, if the input string were say "zzbbaa" it would give the output;
"Duplicate: a, count: 2"
"Duplicate: b, count: 2"
"Duplicate: z, count: 2"
How can I change this so the output returns the duplicates in order of appearance in the string?
You can go through the string again, printing out the duplicate the first time it's found.
Here's code as I would write it. There's no need for dynamic allocation of memory -- the count array can go on the stack, and *(str + i) is much better written str[i].
#include <stdio.h>
#include <limits.h>
void printDups(unsigned char *s) {
int count[UCHAR_MAX+1] = {0};
int dupes = 0;
for (int i = 0; s[i]; i++) {
count[s[i]]++;
dupes = dupes || (count[s[i]] > 1);
}
for (int i = 0; s[i]; i++) {
if (count[s[i]] > 1) {
printf("Duplicate letter: %c, Occurrences: %d\n", s[i], count[s[i]]);
count[s[i]] = 0;
}
}
if (!dupes) {
printf("No duplicates found\n");
}
}
int main(int argc, char**argv) {
unsigned char s[] = "hello world";
printDups(s);
}

Code can't get an n-digit numbers from a string in C

I wanna ask how it can not get integer from a string
for example, here are my code:
int main() {
char str[] = "ababbababa-1998";
int nr = atoi(str);
printf("%d\n", nr);
return (EXIT_SUCCESS);
}
when running, it print out 0 but not 1998, how can I fix it ?
In your case you can use strtok.
int main() {
char str[] = "ababbababa-1998";
char * const first_part = strtok(str, "-");
if (first_part == NULL) {
return 1;
}
char * const second_part = strtok(NULL, "-");
if (second_part == NULL) {
return 1;
}
int nr = atoi(second_part);
printf("%d\n", nr);
return 0;
}
You can look at Why is there no strtoi in stdlib.h? for error check atoi.
Keep walking down str() until code finds something numeric using strtol().
int main() {
char str[] = "ababbababa-1998";
char *p = str;
char *endptr;
while (*p) {
long number = strtol(p, &endptr, 10);
// Was conversion successful?
if (endptr != p) {
printf("%ld\n", number);
return EXIT_SUCCESS;
}
p++;
}
puts("No conversion");
return EXIT_FAILURE;
}
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define ASCII '0'
int
main(void) {
char const str[] = "ababbababa-1998";
int i, result = 0;
for (i = 0; str[i]; i++) {
if (isdigit(str[i])) {
result *= 10;
result += str[i] - ASCII;
}
}
printf("number = %d\n", result);
return 0;
}
If you want to extract all the numeric digits from a string you could use this function I created.
You will need these header files for this function to work.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void getNumbers(char data[]) {
int index = 0;
char current;
for( int i = 0; i < strlen(data); ++i ) {
current = data[i];
if (current >= 48 && current <= 57) {
data[index++] = current;
}
}
data[index] = '\0';
}
You can use the above function like this.
char foobar[] = "1A2B3C4D5E6F7G8H9I";
getNumbers(foobar);
printf("%s", foobar);
The above code will output 123456789

Junk values while reversing a string?

My program is to reverse, even though the reverse is being generated but the problem is there is an unwanted junk values too.
I am not able to understand where the problem is.
#include <stdio.h>
#include<string.h>
int main()
{
char ar[100],b[100];
int i,j;
scanf("%s",ar);
j=strlen(ar);
printf("%d",j);
j-=1;
for(i=0;j>=0;i++)
{
b[i]=ar[j];
j--;
}
printf("\n %s",b);
}
This is the output:
You need to add
b[i] = 0;
at the end to terminate the string.
The function printf() depends on the NUL-terminating character as a marker to stop printing, so you should terminate your array with the character '\0'. Also it would be better to make a function to reverse a string:
#include <stdio.h>
#include <string.h>
void m_strrev(char *str, char *output);
int main(void)
{
char ar[100], b[100];
//int i, j;
scanf("%s", ar);
/*j = strlen(ar) - 1;
for (i = 0; j >= 0; i++)
{
b[i] = ar[j];
j--;
}
b[i] = '\0';
printf("%s\n", b);*/
m_strrev(ar, b);
printf("%s\n", b);
}
void m_strrev(char *str, char *output)
{
char *e = str;
while (*e) {
e++;
}
e--;
while (e >= str) {
*output++ = *e--;
}
*output = '\0';
}

string reverse program in C

i have written a program to reverse a string.. But it is not working.. It is printing the same string which is scanned.. What is the problem with the code?
#include <stdio.h>
#include <stdlib.h>
char *strrev(char *s)
{
char *temp = s;
char *result = s;
char t;
int l = 0, i;
while (*temp) {
l++;
temp++;
}
temp--;
for (i = 0; i < l; i++) {
t = *temp;
*temp = *s;
*s = t;
s++;
temp--;
}
return result;
}
int main()
{
char *str;
str = malloc(50);
printf("Enter a string: ");
scanf("%s", str);
printf("%s\n\n", strrev(str));
return 0;
}
for (i = 0; i < l; i++)
You're walking through the entire string, so you're reversing it twice - it won't be reversed after all. Walk only halfways:
for (i = 0; i < l / 2; i++)
Also, try using int len = strlen() instead of the while-not-end-of-string loop, if you're permitted to do so.
You swap the string's content twice.
Use the following code ..
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
char *strrev(char *s)
{
char *temp = s;
char *result = s;
char t;
while (*temp)
temp++;
while (--temp != s)
{
t = *temp;
*temp = *s;
*s++ = t;
}
return result;
}
int main()
{
char *str;
str = (char*)malloc(50);
printf("Enter a string: ");
scanf("%s", str);
printf("%s\n\n", strrev(str));
return 0;
}
The logic is to swap characters from start upto first half with the characters from last of second half, i.e, upto len/2. Just modify your for loop as below & it will work fine for you
for (i = 0; i < l/2; i++) {
you can use this simple code
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int str_len (char *str)
{
char *ptr = str;
while (*str)
str++;
return str - ptr;
}
int main ()
{
char *str;
int length;
str = (char*)malloc(50);
printf("Enter a string: ");
scanf("%s", str);
length = str_len(str) - 1;
for (int i = length ; i >= 0 ; i--)
printf ("%c", str[i]);
return 0;
}
you can use this code to reverse the string
#include<stdio.h>
#include<string.h>
int main()
{
int n,i;
char str2[100],str1[100];
printf("enter teh string 1\n");
gets(str1);
n = strlen(str1);
for(i=0;i<n;i++)
{
str2[n-1-i]=str1[i];
}
printf("%s\n",str2);
}
Actually you are reversing the string twice...so after come to middle of the string, you should terminate the loop that is your loop should be run for half of the string length that is l/2 (in this case). so your loop should be like
for(i = 0; i < i / 2; i++)
swapping the string content twice..
swapping it once will help..
for (i = 0; i < l/2; i++)

Resources