I have this counting substring palindrome code and I want to scanf the string first and then print the count of the total of palindrome in the substring
I tried using %i and %d and it just showed main error
#include <stdio.h>
#include <string.h>
int countSubstrings(char * s)
{
int res = 0;
int left = 0;
int right = 0;
int len = strlen(s);
for (int i = 0; i < len; i++) {
left = i;
right = i;
while (left >= 0 && right < len && s[left] == s[right]) {
res++;
left--;
right++;
}
left = i;
right = i + 1;
while (left >= 0 && right < len && s[left] == s[right]) {
res++;
left--;
right++;
}
}
}
int main ()
{
int res = 0;
int len = strlen(s);
scanf ("%i", &len);
printf ("%d", res);
}
Expected Input:
(words)
Expected output:
(the count of substring)
Modify the main function as follows:
int main (){
char s[100]; // If the maximum length of input is < 100.
scanf("%s",s);// It will scan standard input till whitespace
printf("%d",countSubstrings(s));
}
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;
}
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
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
Suppose n numbers are to be input in a single line without any spaces given the condition that these numbers are subject to the condition that they lie between 1 and 10.
Say n is 6 , then let the input be like "239435"
then if I have an array in which I am storing these numbers then I should get
array[0]=2
array[1]=3
array[2]=9
array[3]=4
array[4]=3
I can get the above result by using array[0]=(input/10^n) and then the next digit
but is there a simpler way to do it?
Just subtract the ASCII code of 0 for each digit and you get the value of it.
char *s = "239435"
int l = strlen(s);
int *array = malloc(sizeof(int)*l);
int i;
for(i = 0; i < l; i++)
array[i] = s[i]-'0';
update
Assuming that 0 is not a valid input and only numbers between 1-10 are allowed:
char *s = "239435"
int l = strlen(s);
int *array = malloc(sizeof(int)*l);
int i = 0;
while(*s != 0)
{
if(!isdigit(*s))
{
// error, the user entered something else
}
int v = array[i] = *s -'0';
// If the digit is '0' it should have been '10' and the previous number
// has to be adjusted, as it would be '1'. The '0' characater is skipped.
if(v == 0)
{
if(i == 0)
{
// Error, first digit was '0'
}
// Check if an input was something like '23407'
if(array[i-1] != 1)
{
// Error, invalid number
}
array[i-1] = 10;
}
else
array[i] = v;
s++;
}
E.g.
int a[6];
printf(">");
scanf("%1d%1d%1d%1d%1d%1d", a,a+1,a+2,a+3,a+4,a+5);
printf("%d,%d,%d,%d,%d,%d\n", a[0],a[1],a[2],a[3],a[4],a[5]);
result:
>239435
2,3,9,4,3,5
You can use a string to take the input and then check each position and extact them and store in an array. You need to check for the numeric value in each location explicitly, as you are accepting the input as a string. For integers taken input as string, there's no gurantee that the input is pure numeric and if it is not, things can go wild.
check this code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char ipstring[64];
int arr[64];
int count, len = 0;
printf("Enter the numbersi[not more than 64 numbers]\n");
scanf("%s", ipstring);
len = strlen(ipstring);
for (count = 0; count < len ; count++)
{
if (('0'<= ipstring[count]) && (ipstring[count] <= '9'))
{
arr[count] = ipstring[count] - '0';
}
else
{
printf("Invalid input detectde in position %d of %s\n", count+1, ipstring );
exit(-1);
}
}
//display
for (count = 0; count < len ; count++)
{
printf("arr[%d] = %d\n", count, arr[count]);
}
return 0;
}
I wrote this code and it works in some cases. Sometimes, however, it fails, and I just can't see why. Can someone please help me spot the error?
It works for:
String: ishanthakkar ishan
patter: ishan
But it fails for:
String: cpr ograming
patter: cpr
Source:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *compute_prefix_function(char *pattern, int psize)
{
int k = -1;
int i = 1;
int *pi = malloc(sizeof(int)*psize);
if (!pi)
return NULL;
pi[0] = k;
for (i = 1; i < psize; i++) {
while (k > -1 && pattern[k+1] != pattern[i])
k = pi[k];
if (pattern[i] == pattern[k+1])
k++;
pi[i] = k;
}
return pi;
}
// This function find matching string in O(n) time, so iterate through text string only once, when unmatching character found; it proceed with next character and start comparing with first character of string to be searched i.e pattern
int kmp(char *target, int tsize, char *pattern, int psize)
{
int i;
int *pi = compute_prefix_function(pattern, psize);
int k = -1;
if (!pi)
return -1;
for (i = 0; i < tsize; i++) {
while (k > -1 && pattern[k+1] != target[i])
k = pi[k];
if (target[i] == pattern[k+1])
k++;
if (k == psize - 1) {
free(pi);
return i-k;
}
}
free(pi);
return -1;
}
int main(int argc, const char *argv[])
{
char target[200];
char *ch = target;
char pattern[20];
int i;
printf("Enter the string: \n");
fgets(target,100,stdin);
printf("Enter the string to be matched: \n");
fgets(pattern,20,stdin);
i = kmp(target, strlen(target), pattern, strlen(pattern));
if (i >= 0)
printf("matched #: %s\n", ch + i);
getch();
return 0;
}
The fgets function reads and includes the ending CR (or CRLF) in the string.
Add a chomp() function, like
void chomp(char *s) {
int n = strlen(s);
while (n && (s[n-1]==10 || s[n-1]==13)) s[--n] = 0;
}
that removes any CR or LF at the end of the string.
Then chomp() pattern and target before calling kmp() (and after the scanf())
chomp(target);
chomp(pattern);
i = kmp(target, strlen(target), pattern, strlen(pattern));
the program should behave better.
Note: 10 is '\n' (LF) and 13 is '\r' (CR)
Got clue:
i = kmp(target, strlen(target), pattern, strlen(pattern));
was passing string length+1(for null character) so it was giving false result for some text string
i = kmp(target, strlen(target)-1, pattern, strlen(pattern)-1);
works for all cases!
Thanks to all of you for your time!