I have written a C program. It's a character counting program. I will give input as below
Input: ABCAPPPRC
And need as output: A2B1C2P3R1.
But it gives output as A2B1C2A1P3P2P1R1C1. It basically doing as per the logic I have written in program. But I don't want to count the characters of string which have already been counted. Can you suggest what logic I should implement for this?
#include <stdio.h>
int main()
{
char str[30]= "ABCAPPPRC";
char strOutPut[60]="";
char *ptr= &str, *ptr2=&str;
char ch='A';
int count=0;
puts(str);
while (*ptr !=NULL)
{
count =0;
ch = *ptr;
while (*ptr2!= NULL)
{
if (*ptr2 == ch) count++;
ptr2++;
}
printf("%c%d",*ptr, count);
ptr++;
ptr2 = ptr;
}
}
You need to separate the counting from the printing.
The first loop goes through the input and counts the number of occurrences of each character, storing the counts in an array indexed by the character code.
The second loop goes through the array of counts and prints the character corresponding to a non-zero count followed by that count.
For example:
#include <stdio.h>
int main(void)
{
char str[] = "ABCAPPPRC";
int counts[256] = { 0 };
puts(str);
for (char *ptr = str; *ptr != '\0'; ptr++)
counts[(unsigned char)*ptr]++;
for (int i = 0; i < 256; i++)
{
if (counts[i] != 0)
printf("%c%d", i, counts[i]);
}
putchar('\n');
return(0);
}
Sample output:
ABCAPPPRC
A2B1C2P3R1
I could not understand the first for loop. Could you please explain it?
The for control line steps through the string str one character at a time. It is the for loop equivalent of the outer while loop in your original code.
char *ptr = str;
...
while (*ptr != '\0')
{
...
ptr++;
}
The body of the loop converts *ptr (a plain char) into an unsigned char (so that it is guaranteed to be positive), and then uses that value as an index into the array counts. Thus, for example, on the first iteration, A is mapped to 65, and counts[65] is incremented. Thus, for each character code, the loop increments the count corresponding to that character code each time the character is encountered in the string.
The second loop then picks out the non-zero counts, printing the character code as a character followed by its count.
(Incidentally, you should have been getting a compilation warning from the original char *ptr = &str about a type mismatch between char * and char (*)[30]. Learn when to put ampersands in front of array names — you seldom do it unless there is also a subscript after the array name. Thus, &array is usually — but not always — wrong; by contrast, &array[0] is very often valid. Also note that on some machines, NULL is defined as ((void *)0) and this elicits a warning when you compare it to a plain char, as you did with while (*ptr != NULL). You should compare characters to '\0' as in my rewrite; you should reserve NULL for use with pointers.)
str is alerady a character pointer, so when you do this: char *ptr= &str you convert a pointer to pointer to character to a char*. Loose the ampersand(&).
Also in the inner cycle you should check if the given value of ch has already been processed. In the case you use when ptr is pointing to the second A you should just continue, because you have already added the number of A-s in the answer.
Your solution is far from optimal. I strongly suggest you lookup counting sort. It will make your solution faster but also will make it simpler.
# Jonathan your solution is correct only when string characters are given in ascending order like ABCDEF, but it gives problem when character order is changed. Input string is "ABAPPPRCC" and required output is A2B1P3R1C2.
Here in this case your solution will change out put to A2B1C2P3R1.
Below program gives character count without changing string formation.
char *str= "ABAPPPRCC";
char strOutPut[30]="";
char *ptr = str, *ptr2 = str;
char ch='A';
int count=0, i = 0 , total_print = 0;
puts(str);
while (*ptr != '\0')
{
count =0;
ch = *ptr;
while (*ptr2!= '\0')
{
if (*ptr2 == ch) count++;
ptr2++;
}
for( i = 0; i < total_print ; i++ )
{
if ( ch == strOutPut[i] )
{
i = total_print + 1;
break;
}
}
if( i <= total_print )
{
printf("%c%d",*ptr, count);
strOutPut[total_print++] = ch;
}
ptr++;
ptr2 = ptr;
}
#include <stdio.h>
int main(void){
const char noncountchar = '\x11';
char str[30]= "ABCAPPPRC";
char strOutPut[60]="";
char *ptr, *ptr2;
char ch;
int count=0, len=0;
puts(str);
for(ptr=str;ch=*ptr;++ptr){
if(ch == noncountchar) continue;
count =1;
for(ptr2=ptr+1;*ptr2;++ptr2){
if (*ptr2 == ch){
*ptr2 = noncountchar;
++count;
}
}
len += sprintf(strOutPut+len, "%c%d", *ptr, count);
}
printf("%s", strOutPut);
return 0;
}
Related
#include <stdio.h>
int strcompare (char*);
int main (int argc, char *argv[])
{
int argIndex;
for(argIndex = 1; argIndex <= argc; argIndex++)
{
strcompare(argv[argIndex]);
printf("%s has %d letters in it\n", argv[argIndex], strcompare(argv[argIndex]));
}
return 0;
}
int strcompare (char *str)
{
int index, letterDex = 0;
for (index = 0; *str != '0'; index++)
{
letterDex++;
}
}
The assignment is to count the number of letters in a word, when I compile I don't get any errors, but when I try to run it it just doesn't work at all
./cma_length noah bruh conner
and nothing comes after it when I hit enter.
Four problems:
missing the return statement on your strcompare
youwasn't updating the pointer of the char*
in C array that have 4 element, has the last element in index 3, so in the for loop condition, you have to check for<, not for <=
*str != '0' is wrong, you are checking if the char is the char 0, not the escape char, which is \0 so check for this char in this way *str != '\0'
With those things done, the code will be this:
#include <stdio.h>
int strcompare (char*);
int main (int argc, char *argv[])
{
int argIndex;
for(argIndex = 1; argIndex < argc; argIndex++){
strcompare(argv[argIndex]);
printf("%s has %d letters in it\n", argv[argIndex], strcompare(argv[argIndex]));
}
return 0;
}
int strcompare (char *str){
int letterDex;
for (letterDex = 1; *str != '\0'; letterDex++){
str++;
}
return letterDex;
}
Also the index variable was useless, so i've just removed it
It doesn't look like code which compiles. The function strcompare should return an int and in the implementation above it doesn't return anything. I assume there's a return letterDex; at the end of your function but you lost it when copying the code here.
In the for loop in the strcompare function you're comparing the *str to '0'. Now there are two things that are wrong here I think:
You're comparing *str to '0' but you don't change the pointer value. So you're comparing the first character to '0' all the time. You should either do str[index] != '0' or instead of using index increment the pointer.
I think that you want to look for a '\0' instead of '0'. The '\0' is a null terminator character meaning the end of the string.
The reason why you're not seeing anything happening is because you're stuck in an infinite loop.
I am blocked at solving a problem in the book.
The problem is:
read a word and output the string backwards, and output it backwards,
you should print the palindrome if it is the same as the original.
Also, do not use a library such as string.h, but include stdio.h
only.
So I created the code below.
#include <stdio.h>
int main()
{
char str[128];
char temp;
int leng = 0;
char a;
scanf("%s", str);
{
a = str;
}
while(str[leng] != '\0')
leng++;
for (int i = 0; i < leng/2; i++)
{
temp = str[i];
str[i] = str[leng - i - 1];
str[leng - i - 1] = temp;
}
printf("%s\n", str);
{
if (a == str)
printf("palindrome\n");
}
return 0;
}
The output in reverse order was easily solved, but I blocked in the process at printing palindrome. I tried to print the palindrome only when the input and output values are the same.
However, if (a == str) I used was a code to compare address values.
Also,I thought that it would be useful to implement strcmp as a loop, but I can not find a way to compare the input value with the output value using strcmp.
Is there a way to compare the input and output values in C? Or is there a way to make palindrome print only under certain circumstances (input = output)?
I am wondering if I can code the input value = output value in C exactly.
Note that my code prints the palindrome when the address values are the same. So I haven't seen yet :(
Here is a loosely written untested code that should resolve your issues.
char str[128];
if( fgets( str, 128, stdin ) )
{
/* I hate this but restriction on string.h
Calculate the size of this string */
size_t s_len = 0;
char *p = str;
for( ; *p && *p != '\n' ; p++ )
s_len++;
/* trim down nextLine characters */
if( p && *p == '\n' )
{
*p = '\0';
}
if( s_len == 0 )
{
/* Should never be the case here */
exit(0);
}
/* This should handle both cases of reversing and pallindrom */
int isPallindrom = 1; /* Lets Say Yes for now*/
for( size_t i = 0, j = s_len-1; i < j ; i ++, j -- )
{
if( str[i] != str[j] )
isPallindrom = 0; // Not a pallindrom
swap( str, i, j); // Write a swap function here
}
/* at this point you should have
1. a reversed string in a
2. based on isPallindrom value a confirmation if it really a pallindrom */
}
There are some fundamental errors in your code for instance
a = str;
if (a == str)
turn on warnings while compilation to catch these well before execution.
edit - swap for you.
void swap( char *s, size_t i, size_t j )
{
char t = s[i];
s[i] = s[j];
s[j] = t;
}
Use this function:
int compare(char *str1, char *str2)
{
while(*str1 && *str2){
if(*str1 == *str2){
str1++;
str2++;
}
else return (*str2 - *str1);
}
if(*str1)
return -1;
if(*str2)
return 1;
return 0;
}
Logic:
Until '\0' is encountered in one of the strings, check the character in either string. If the characters are equal, continue. Otherwise, return a negative number of the character in string1 > string2, or a positive number if the character in string1 < string2.
Once a '\0' is encountered, check if string1 has any more characters. If yes, it is the greater string, hence return a negative number.
If string1 doesn't have any more characters, check string2. If that too has no more characters, return 0. Otherwise return a positive number.
I am trying to pass a C string (char*) to a function lower(char *) (as in the prototype) that returns a C string char *lower() to main(). But I am not getting the desired output. Point out my mistakes and suggest some techniques for getting the result.
(Note : <string.h> functions are not allowed & the task must be done with pointers). Here is my code,
#include <stdio.h>
#include <stdlib.h>
char *lower(char *);
void main() {
char pass[10], *pass1;
printf("Enter a password\n");
scanf("%s", pass);
pass1 = lower(pass);
printf("Lower case ");
int i = 0;
while (*pass1 != '\0') {
printf("%c", *(pass1 + i));
i++;
}
}
char *lower(char *p) {
while (*p != '\0') {
if (*p >= 'A' && *p <= 'Z') {
*p = *p + 32;
}
p++;
}
return p;
}
There are multiple problems in your code:
main should have the prototype int main(void) a for good style have a return 0; statement at the end of the body.
scanf() should protect the destination array from overflow by specifying the maximum number of characters to read into it: scanf("%9s", pass); and you should check its return value for successful conversion.
you should use pass1[i] instead of *(pass1 + i). Both expressions are equivalent but the first is more readable. Incidentally, another equivalent but surprising alternative is i[pass1], don't use it unless you want to confuse the reader, which might be advisable in a password handling routine.
printing individual characters with printf("%c", pass1[i]) does not seem mandated by the rules posted: use a single printf statement.
Furthermore, the loop test is constant: while (*pass1 != '\0') as you only increment i in the loop. Hence an infinite loop and undefined behavior when you access elements of pass beyond its end.
as you pass the return value to printf(), function lower() should return the original pointer, not the pointer to the end of the argument string.
you should not hard-code the difference between lowercase and uppercase characters, 32 only works for ASCII, not EBCDIC. *p += 'a' - 'A'; would be both more portable and more readable. It works for both ASCII and EBCDIC, but might not for other less common character sets and the test if (*p >= 'A' && *p <= 'Z') is not precise enough for EBCDIC as the uppercase letters do not form a contiguous set. Use the macros from <ctype.h> for a portable solution.
Here is a corrected version:
#include <stdio.h>
#include <ctype.h>
char *lower(char *);
int main(void) {
char pass[80];
printf("Enter a password\n");
if (scanf("%79s", pass) == 1) {
printf("Lower case: %s\n", lower(pass));
}
return 0;
}
char *lower(char *s) {
for (char *p = s; *p != '\0'; p++) {
*p = tolower((unsigned char)*p);
}
return s;
}
If you cannot use <ctype.h>, use this less portable version:
char *lower(char *s) {
for (char *p = s; *p != '\0'; p++) {
if (*p >= 'A' && *p <= 'Z')
*p += 'a' - 'A';
}
return s;
}
char *lower(char *p){
char *ptr = p;
while(*p != '\0'){
if( *p>='A' && *p<='Z' ){
*p = *p + 32;
}
p++;
}
return ptr;
}
why sometimes is good to return something like converted char pointer - to use it in other operations - for example as a parameter in another function call.
This program is supposed to dynamically store each string entered into a pointer. Each pointer is part of an array of pointers that will collectively hold all of the strings. When the user enter an empty word, or NULL, it is supposed to quit. My problem is that the code just skips over the NULL conditional statement. I saw some similar posts and have been at it for hours but just can't solve it.
#include <stdio.h>
#include <string.h>
void readWord(char wordChar[], int MAX_CHARS);
int main()
{
int MAX_CHARS = 20;
int wCount = 0;
char *wordArray[wCount]; // Array of pointers that will each point to wordChar
char wordChar[MAX_CHARS];
int i;
for(i = 0;;i++)
{
wCount++;
printf("Enter word: ");
readWord(wordChar, MAX_CHARS); //Reads one word at a time
//Dynamically store each
wordArray[i] = (char*) malloc((int) strlen(wordChar) * (int) sizeof(char));
wordArray[i] = wordChar;
printf("%s \n", wordArray[i]); //Troubleshooting *********************
// If loop ends scanning when word is NULL
if(wordArray[i] == 'NULL')
{
printf("if loop");
break;
}
else printf("no loop");
}
}
/***********************************************************/
void readWord(char wordChar[], int MAX_CHARS)
{
int letter, i = 0;
while((letter = getchar()) != '\n')
{
if(i < MAX_CHARS)
{
wordChar[i] = letter;
i++;
}
}
wordChar[i] = '\0';
}
The short and useless summary is: you're #includeing string.h; use it!
You're trying to compare two pointers directly.
if(wordArray[i] == 'NULL')
This line looks at the pointer value of wordArray[i] to the value of the multi-character literal 'NULL' (note that I didn't say string: you used single quotes here, so 'NULL' has the integer value 0x4e554c4c; see https://stackoverflow.com/a/7459943/510299). If wordArray[i] points to the address 0x12345678, then this is comparing 0x12345678 to 0x4e554c4c and sees that they're not equal.
What you want is to compare strings. In C, you can't do this with == because C strings are char arrays or pointers to chars; == compares the pointer (address) value, as I noted above.
Solution, use strcmp.
if(strcmp(wordArray[i], "NULL") == 0)
(Note the use of double quotes.)
EDIT: Also note that char *wordArray[wCount]; is declared when wCount == 0. This nominally means you tried to declare an array of length 0, which is undefined behaviour. You need to declare wordArray with some length (probably the maximum number of words you can store). [Thanks to riodoro1 for pointing this out in a comment.]
You made a similar blunder with string manipulation in C here:
wordArray[i] = (char*) malloc((int) strlen(wordChar) * (int) sizeof(char));
This line sets the pointer wordArray[i] to some newly allocated memory.
wordArray[i] = wordChar;
This line then proceeds to change the pointer wordArray[i] to point to the original location where the read word was stored. Oops. The next time you go through this loop, wordChar changes, and wordArray[i] is pointing to wordChar... so the new word "replaces" all the previous words.
Solution? You need to copy the string to the memory you just malloc'd. Use strcpy().
printf("if loop");
A conditional (if) statement is not a kind of loop.
#include <stdio.h>
#include <stdlib.h> //for realloc and free (malloc)
#include <string.h>
void readWord(char wordChar[], int MAX_CHARS);
int main(void){
int MAX_CHARS = 20;
int wCount = 0;
char **wordArray = NULL; // Array of pointers that will each point to wordChar
char wordChar[MAX_CHARS];
int i;
for(i = 0;;i++){
printf("Enter word: ");
readWord(wordChar, MAX_CHARS); //Reads one word at a time
if(*wordChar == '\0' || strcmp(wordChar, "NULL") == 0){//empty word or "NULL"
putchar('\n');
break;
}
wCount++;
wordArray = realloc(wordArray, wCount * sizeof(*wordArray));//check omitted
//Dynamically store each
wordArray[i] = malloc(strlen(wordChar) + 1);//+1 for NUL
strcpy(wordArray[i], wordChar);//copy string
}
//check print and free
for(i = 0; i < wCount; ++i){
printf("'%s'\n", wordArray[i]);
free(wordArray[i]);
}
free(wordArray);
return 0;
}
void readWord(char wordChar[], int MAX_CHARS){
int letter, i = 0;
while((letter = getchar()) != '\n' && letter != EOF){
if(i < MAX_CHARS -1)//-1 for NUL, or char wordChar[MAX_CHARS+1];
wordChar[i++] = letter;
else
;//drop letter upto newline
}
wordChar[i] = '\0';
}
i need to get the ascii (int and hex format) representation of a string char by char. For example if i have the string "hello", i would get for int ascii 104 101 108 108 111
and for hex 68 65 6C 6C 6F
How about:
char *str = "hello";
while (*str) {
printf("%c %u %x\n", *str, *str, *str);
str++;
}
In C, A string is just a number of chars in neighbouring memory locations. Two things to do: (1) loop over the string, character by character. (2) Output each char.
The solution for (1) depends on the string's representation (0-terminated or with explicit length?). For 0-terminated strings, use
char *c = "a string";
for (char *i = c; *i; ++i) {
// do something with *i
}
Given an explicit length, use
for (int i = 0; i < length; ++i) {
// do something with c[i]
}
The solution for (2) obviously depends on what you are trying to achieve. To simply output the values, follow cnicutar's answer and use printf. To get a (0-terminated) string containing the representation,
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* convert a 0-terminated string to a 0-terminated string of its ascii values,
* seperated by spaces. The user is responsible to free() the result.
*/
char *to_ascii(const char *inputstring) {
// allocate the maximum needed to store the ascii represention:
char *output = malloc(sizeof(char) * (strlen(inputstring) * 4 + 1));
char *output_end = output;
if (!output) // allocation failed! omg!
exit(EXIT_FAILURE);
*output_end = '\0';
for (; *inputstring; ++inputstring) {
output_end += sprintf(output_end, "%u ", *inputstring);
//assert(output_end == '\0');
}
return output;
}
If you need to output an explicit-length string, use strlen() or the difference (size_t)(output_end-output).
int main()
{
enum type {decimal, hexa};
char *str = "hello";
char *temp_str = NULL;
temp_str = str;
static enum type index = decimal;
while (*str) {
if(index == decimal)
printf("%u\t", *str);
else
printf("%x\t",*str);
str++;
}
printf("\n");
if(index != hexa)
{
index = hexa;
str = temp_str;
main();
}
}
hope this will work fine as what u want, and if u want to store it in a uint8_t array, have to just declare an variable for it.
I know this is 5 years old but my first real program converted strings to ASCII and it was done in a clean and simple way by assigning a variable to getchar() and then calling it in printf() as an integer, all while it's in a loop of course, otherwise getchar() only accepts single characters.
#include <stdio.h>
int main()
{
int i = 0;
while((i = getchar()) != EOF)
printf("%d ", i);
return 0;
}
and here's the original version using the for() loop instead because I wanted to see just how small I could make the program.
#include <stdio.h>
int main()
{
for(int i = 0; (i = getchar()) != EOF; printf("%d ", i);
}
/* Receives a string and returns an unsigned integer
equivalent to its ASCII values summed up */
unsigned int str2int(unsigned char *str){
int str_len = strlen(str);
unsigned int str_int = 0;
int counter = 0;
while(counter <= str_len){
str_int+= str[counter];
printf("Acumulator:%d\n", str_int);
counter++;
}
return str_int;
}