Spaces shouldn't be counted to string length - c

This code gets user input then 256 % length of string is used. If the result is 3 and the input is abc the output is bcd. This works fine. However if the input is for example "hey whatsup" the length is 11 and it should be 10 because the space shouldn't be included for the length.
How can I programm this code so it dosen't count space to the length?
Is it even possible to implement it while using fgets?
Thank you in advance.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char array[20];
int length = 0;
int i;
int key = 256;
printf("input: ");
fgets(array, 20, stdin);
length = strlen(array) - 1;
key = key % length;
if (key > 0) {
for (i = 0; i < length; i++) {
if (array[i] == ' ') {
printf("%c", array[i]);
continue;
}
array[i] = array[i] + key;
printf("%c", array[i]);
}
}
return 0;
}

1) If you don't want to include the spaces in the calculation of the key, you have to make your own function to calculate the number of spaces.
2) The code length = strlen(array) - 1; seems to "take care" of a '\n' in the end of the string. However, you can't be sure that there is a '\n'. You need to check for that first.
3) Doing key % 0 will be "bad" so check for that as well
The code could look something like:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int cnt_spaces(char* arr)
{
int res = 0;
while(*arr)
{
if (*arr == ' ')
{
++res;
}
++arr;
}
return res;
}
int main() {
char array[20];
int length = 0;
int i;
int key = 256;
printf("input: ");
fgets(array, 20, stdin);
length = strlen(array);
if (strlen(array) == 0) return 0; // or add error handling
// Remove \n if present
if (array[length-1] == '\n')
{
array[length-1] = '\0';
--length;
}
printf("len = %d\n", length);
int spaces = cnt_spaces(array);
printf("spaces = %d\n", spaces);
if (length == spaces) return 0; // or add error handling
key = key % (length - spaces);
printf("key = %d\n", key);
if (key > 0) {
for (i = 0; i < length; i++) {
if (array[i] != ' ') {
array[i] = array[i] + key;
}
printf("%c", array[i]);
}
}
return 0;
}
Example:
input: a b c
len = 5
spaces = 2
key = 1
b c d

Related

i'm having some problem with saveing the vaule of the longest fence

I'm having some problem with saveing the vaule of the longest fence.
I tried this:
int longestFence(char input [], int size)
{
int i , max = 0, count = 0;
for(i = 0; i < size ; i++)
{
if(input[i] == '|' && input[i] == '-')
{
count = 1;
}
if(input[i] != input[i + 1])
{
count++ - 1;
}
}
return count;
}
In practice, to detect is the fence is still valid, you just have to check if the current symbol is different or not than the previous one.
You also have to check if the current count is longer or not than the previous longest one.
Besides, I modified the random string generator: the current one is rather inefficient.
In addition, the string generated is not terminated by the Null character. I also modified it.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 10
int longestFence (char input[], int size) {
if (size == 0) return 0;
int max_count = 0;
int count = 1;
for (int i = 1; i < size; ++i) {
if (input[i] != input[i-1]) {
count++;
} else {
if (count > max_count) max_count = count;
count = 1;
}
}
if (count > max_count) max_count = count;
return max_count;
}
int main() {
char string[MAX+1];
char symbols[] = {'|', '-'};
srand (time(NULL));
int length = rand() % (MAX+1);
for (int i = 0; i < length; ++i) {
int val = (rand() / 16) % 2;
string[i] = symbols[val];
}
string[length] = '\0';
printf ("String is: %s\n", string);
printf ("Longest fence = %d\n", longestFence (string, length));
return 0;
}

Unique character count function does not take into consideration all lines (C)

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;
}

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

scanf in while loop not evaluating first block of information

Trying to get scanf to iterate and evaluate each section of the string with isdigit. However it seems to be skipping the first 'block' thus offsetting everything. Recommendations on what I'm doing wrong?
int main (void) {
int icount = 0;
int c = 0;
int compare = 0;
int len = 0;
char s[256] = "";
printf("Enter a string:\n\n");
while (scanf("%s", s) == 1) {
scanf("%255s", s);
len = strlen(s);
printf("the string is %d characters long\n", len);
while (len > 0) {
printf("c is on its s[%d] iteration\n", c);
if (isdigit(s[c])) {
compare = compare + 1;
}
c++;
len--;
}
if (compare == strlen(s)) {
icount = icount + 1;
}
c++;
}
printf("\ni count is %d\n", icount);
return 0;
}
When I run it I keep getting data back like this:
./a
Enter a string:
17 test 17
the string is 4 characters long
c is on its s[0] iteration
c is on its s[1] iteration
c is on its s[2] iteration
c is on its s[3] iteration
the string is 2 characters long
c is on its s[5] iteration
c is on its s[6] iteration
i count is 0
From the comments above, I believe this might be what you are looking for
#include <ctype.h>
#include <stdio.h>
int main (void)
{
int icount;
int index;
char string[256];
printf("Enter a string:\n\n");
icount = 0;
while (scanf("%255s", string) == 1)
{
int isNumber;
isNumber = 1;
for (index = 0 ; ((string[index] != '\0') && (isNumber != 0)) ; ++index)
{
printf("index is on its string[%d] iteration\n", index);
if (isdigit(string[index]) == 0)
isNumber = 0;
}
if (isNumber != 0)
icount += 1;
}
printf("\nicount is %d\n", icount);
return 0;
}
ended up going with this simple code as my knowledge level is... well... simple
. thanks for the help with that iteration and second scanf it was about to drive me over the edge!
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main (void) {
int icount = 0;
int c = 0;
int compare = 0;
char s[256] = "";
printf("Enter a string:\n\n");
while (scanf("%255s", s) == 1) {
compare = 0;
for (c = 0 ; s[c] != '\0' ; c++) {
if (isdigit(s[c])) {
compare = compare + 1;
}
}
if (compare == strlen(s)) {
icount = icount + 1;
}
}
printf("%d integers\n", icount);
return 0;
}

How to exit scanf loop when there is a space

For example, the user shall put the input like that, "ABC123," but not "ABC 123" or "A BC123."
Here is my code:
unsigned int convert_to_num(char * string) {
unsigned result = 0;
char ch;
//printf("check this one %s\n", string);
while(ch =*string++) result = result * 26 + ch - 'A' + 1;
return result;
}
int main()
{
char input_string[100];
char arr_col[100] = {'\0'};
char arr_row[100] = {'\0'};
int raiseflag;
int started_w_alpha =0;
int digitflag = 0;
while(scanf("%s", &input_string) != EOF) {
int i = 0, j = 0, digarr = 0;
while (i <=5) {
if (input_string[i] == '\0') {printf("space found!");}
if ((input_string[i] >= 'A' && input_string[i] <= 'Z') && (digitflag == 0)) {
started_w_alpha = 1;
arr_col[j] = input_string[i]; j++;
}
//printf("something wrong here %s and %d and j %d\n", arr_holder, i, j);
if (started_w_alpha == 1) {
if (input_string[i] >=48 && input_string[i]<=57){ digitflag = 1; arr_row[digarr] =input_string[i]; digarr++; }
}
i++; if (i == 5) { raiseflag =1; }
}
printf(" => [%d,%s]\n", convert_to_num(arr_col), arr_row);
if (raiseflag == 1) { raiseflag = 0; memset(arr_col, 0, 5); memset(input_string, 0, 5); memset(arr_row, 0, 5); digitflag = 0; started_w_alpha = 0; }
}
return 0;
}
Apparently, \0 doesn't work in my case because I have an array of 5 and user can put 2 chars. I want to exit the loop whenever a space is found in between the characters.
This is the whole code. I added {'\0'} my array because of the extra characters I get when there is less than 5 characters.
Thanks!
Since the index is starting from 0 and input_string[5]; array size is 5, the only valid indexes are from 0 to 4.
but your loop while (i <=5) { go till 5, it is mean you exceed the array.
If you insert 5 characters to the string, the terminating null is the 6th.
Since you exceed the array it written over some other variable. but you still can find it when you check input_string[5]
So if you want to insert 5 characters you array size should be at least 6
char input_string[6];
if you want to check only the first 5 elements you'll have to change the loop to:
while (i < 5) {
and as I wrote in the comment if you find the terminating null, no use to continue the loop, since it contain garbage or leftover from the previous iteration.
Therefor you should break if it found, like this:
if (input_string[i] == '\0') {printf("space found!"); break;}
EDIT
check this program: it use fgets to read the whole input, then search for white spaces.
Note it doesn't trim the input, means it won't remove spaces when thay appear at the beginning or at the end of the input.
#include <ctype.h>
#include <string.h>
#include <stdio.h>
int main()
{
int i ,size;
char input_string[100];
fgets(input_string,100,stdin);
i=0;
size = strlen(input_string);
while (i<size-1){ //enter is also count
if (isspace(input_string[i]))
{
printf("space found!");
break;
}
i++;
}
return 0;
}
EDIT2
Now with a trim, so it will remove leading and ending spaces:
#include <ctype.h>
#include <string.h>
#include <stdio.h>
char* trim(char *input_string)
{
int i=0;
char *retVal = input_string;
i = strlen(input_string)-1;
while( i>=0 && isspace(input_string[i]) ){
input_string[i] = 0;
i--;
}
i=0;
while(*retVal && isspace(retVal[0]) ){
retVal ++;
}
return retVal;
}
int main()
{
int i ,size;
char input_string[100],*ptr;
fgets(input_string,100,stdin);
ptr = trim(input_string);
i=0;
size = strlen(ptr);
while (i<size){
if (isspace(ptr[i]))
{
printf("space found!");
break;
}
i++;
}
return 0;
}

Resources