passing char array to function from scanf in c - c

I have following function in c code
void analyze_text(char text[]) {
...
for (int i = 0; i < text_length || text[i] != '\0'; i++) {
...
}
}
In main function i would like to pass some string to it. If i do something like this
char text[4000] = "some text here";
analyze_text(text);
this is cool and do the goal, but i would like to have some user input present and I am not sure how to get char[] out of it. I tried following 2 and none of them seemed to work:
char text[4000];
scanf("%s",text);
analyze_text(text);
OR
char text[4000];
int c;
int count=0;
c = getchar();
count = 0;
while ((count < 4000) && (c != EOF)) {
text[count] = c;
++count;
c = getchar();
}
analyze_text(text);
I know that the first one should return pointer to char array, but second one should return char array itself, or not?
Its been like 10 years since i havent been working with c/c++. Can anybody give me some hint please?
update (whole function):
void analyze_text(char text[]) {
int printable_text_length = 0;
int text_length = strlen(text);
int word_count = 0;
int sentence_count = 0;
int in_sentence = 0;
int in_word = 0;
int count[ASCII_SIZE] = { 0 };
for (int i = 0; i < text_length || text[i] != '\0'; i++) {
int c = text[i];
if (!isspace(c)) {
printable_text_length++;
}
if (isalpha(c)) {
in_word = 1;
in_sentence = 1;
count[tolower(c)]++;
}
if (text[i] == ' ' && text[i + 1] != ' ' && in_word==1) {
word_count++;
in_word = 0;
}
if (text[i] == '.' && in_sentence==1) {
sentence_count++;
in_sentence = 0;
}
}
if (in_word == 1) { word_count++; }
if (in_sentence == 1) { sentence_count++; }
char charIndexes[ASCII_SIZE];
for (int i = 97; i <= 122; i++) {
charIndexes[i] = i;
}
for (int i=97; i <= 122; i++) {
for (int j = i + 1; j <= 122; j++) {
if (count[i] > count[j]) {
int temp = count[j];
count[j] = count[i];
count[i] = temp;
int temp2 = charIndexes[j];
charIndexes[j] = charIndexes[i];
charIndexes[i] = temp2;
}
}
}
...printf...
}

The issue with
char text[4000];
scanf("%s",text);
analyze_text(text);
is that scanf identifies space-separated chunks, so you'll only read the first one.
In order to read up to a whole line from the user, try fgets:
char text[4000];
fgets(text, 4000, stdin);
analyze_text(text);
You may want to check the return value of fgets for error detection.

You can use dyanamic array of char to pass it into the function.
Here is the code
#include <stdio.h>
#include <stdlib.h>
void analyze_text(char* text) {
for (int i = 0; text[i] != '\0'; i++) {
printf("%c\n",text[i] );
}
}
int main() {
char* text = (char *)malloc(4000 * sizeof(char));
scanf("%s", text);
analyze_text(text);
return 0;
}
and here is the output with input = 'abhishek'
a
b
h
i
s
h
e
k
remember that strlen in dyanamc array will not give the length of input array.

Related

How to get the most frequent letter in a word?

I am trying to get the most frequent letter in a string with only uppercased letters and no spaces between words. to do that I used a function maxArray(array, sizeof array) that gives the biggest number in the array in order to count how many times the letter is repeated and store the info in another array in the same position of each letter in the string. But in the two algorithms I have came up with it doesn't work.
PS: I am just a beginner.
Here is the code:
int maxArray(int *tab, int n) {
int i, tmp;
tmp = tab[0];
for (i = 1; i < n; i++) {
if (tmp < tab[i])
tmp = tab[i];
}
return tmp;
}
//first algo(didn't finish it)
char occurencedelettre(char *string) {
int *array;
int i, j, compt, max;
for (i = 0; string[i] !='\0'; i++) {
compt = 0;
for (j = 0; string[j] !='\0'; j++) {
if (string[i] == string[j])
compt++;
}
array[i] = compt;
}
return array;
}
//second one
char occurencedelettre(char *string) {
int count[25] = { 0 };
int x = 0;
char result;
for (int i = 0; string[i] != '\0'; i++) {
count[string[i]]++;
if (x < count[string[i]]) {
x = count[string[i]];
result = string[i];
}
}
return result;
}
The second approach is almost correct except for these problems:
the array should have a length of 26
you must subtract 'A' from the value of the letter to get an index between 0 and 25, assuming the word only contains uppercase letters in ASCII.
you must intialize result to return 0 (or any other specific value) for an empty word.
Here is a modified version:
char occurencedelettre(const char *string) {
size_t count[26] = { 0 };
size_t x = 0;
char result = '\0';
for (size_t i = 0; string[i] != '\0'; i++) {
count[string[i] - 'A']++;
if (x < count[string[i]]) {
x = count[string[i]];
result = string[i];
}
}
return result;
}
The first approach is more cumbersome and slower, but also more generic as it may work for any word contents. Here is a modified version:
char occurencedelettre(const char *string) {
char result = 0;
size_t max_count = 0;
for (size_t i = 0; string[i] != '\0'; i++) {
size_t count = 1;
for (size_t j = i + 1; string[j] != '\0'; j++) {
if (string[i] == string[j])
count++;
}
if (max_count < count) {
max_count = count;
result = string[i];
}
}
return result;
}
Note that you can adapt the first approach for any word contents, assuming 8-bit bytes:
char occurencedelettre(const char *string) {
size_t count[256] = { 0 };
size_t x = 0;
char result = '\0';
for (size_t i = 0; string[i] != '\0'; i++) {
count[(unsigned char)string[i]]++;
if (x < count[(unsigned char)string[i]]) {
x = count[(unsigned char)string[i]];
result = string[i];
}
}
return result;
}

Selection of unique characters

Please, help with the code.
Requirement:
Write a function my_union that takes two strings and returns, without doubles, the characters that appear in either one of the strings.
Example:
Input: "zpadinton" && "paqefwtdjetyiytjneytjoeyjnejeyj"
Output: "zpadintoqefwjy"
My code:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
char *my_union(char *a, char *b) {
char *str;
// Algorithm for excluding nonunique characters from string a(given in
// parameters).
str[0] = a[0];
int k = 1;
str[k] = '\0';
for (int i = 1; a[i] != '\0'; i++) {
bool is = true;
for (int j = 0; str[j] != '\0'; j++) {
if (str[j] == a[i]) {
is = false;
break;
}
}
if (is) {
str[k] = a[i];
k++;
str[k] = '\0';
}
} // In this case we are excluding excess character 'n' from "zpadinton", so
// str is equal to "zpadinto".
// Algorithm for adding unique characters from array b(given in parameters)
// into str.
for (int i = 0; b[i] != '\0'; i++) {
bool is = true;
for (int j = 0; str[j] != '\0'; j++) {
if (str[j] == b[i]) {
is = false;
break;
}
}
if (is) {
strncat(str, &b[i], 1);
}
}
return str;
}
The first algorithm is almost identical with second, but it doesn't work(. Mb I messed up with memory, give some advice, pls.
If you mean, get the unique characters from two strings and store them into a new string, try this code ;
First, you must allocate a memory for str. In your code, str is not pointing allocated memory location, so you will probably get segmentation fault.
int contains(const char * str,char c)
{
for (int i = 0; i < strlen(str); ++i)
if(str[i] == c)
return 1;
return 0;
}
char * my_union(char *a, char*b)
{
char * res = (char*)malloc(sizeof(char)*(strlen(a) + strlen(b)));
int pushed = 0;
for (int i = 0; i < strlen(a); ++i)
{
if(!contains(res,a[i])){
res[pushed] = a[i];
pushed++;
}
}
for (int i = 0; i < strlen(b); ++i)
{
if(!contains(res,b[i])){
res[pushed] = b[i];
pushed++;
}
}
return res;
}
int main(int argc, char const *argv[])
{
char string1[9] = "abcdefgh";
char string2[9] = "abegzygj";
char * result = my_union(string1,string2);
printf("%s\n", result);
return 0;
}
Also, do not forget the free the return value of my_union after you done with it.

Function that takes a string and "filters out" all the non digit characters and all but the first dot in C?

For example: Say that the string is "90.%7."
The function would filter out the % and the second dot.
The function would thus return "90.7"
I'm flexible as to how it would return it.
Everything i have done so far hasn't worked. Sad Face.
Thanks.
Edit: I figured out how to do it.
Check out this code
void filter(const char * input, char * output)
{
int length = strlen(input);
int dot_was_seen = 0;
int i;
int j = 0;
for( i = 0 ; i < length ; i++)
{
if(input[i] >= 0x30 && input[i] <= 0x39)
output[j++] = input[i];
else if(!dot_was_seen && input[i] == 0x2E)
{
output[j++] = input[i];
dot_was_seen = 1;
}
}
output[j] = 0;
}
int main()
{
char input[] = "90.%7.";
char output[32];
filter(input, output);
printf(output);
return 0;
}

replacing integers with strings in C

I wrote code that replaces integers from 0 to 3 with strings. I was only allowed to use getchar() and putchar(). If the input is 1, the output will become "one".
#include <stdio.h>
int main()
{
int c;
char* arr[4] = {"zero", "one", "two","three"};
int i;
while ((c = getchar ()) != EOF)
{
if(c==0+'0') {
char* str = arr[0];
for (i = 0; str[i] != '\0'; i++) {
putchar(str[i]);
}
}
else if(c==1+'0') {
char* str = arr[1];
for (i= 0; str[i] != '\0';i++) {
putchar(str[i]);
}
}
else if(c==2+'0') {
char* str = arr[2];
for (i = 0; str[i] != '\0'; i++) {
putchar(str[i]);
}
}
else if(c==3+'0') {
char* str = arr[3];
for (i = 0; str[i] != '\0'; i++) {
putchar(str[i]);
}
}
else
putchar(c);
}
return 0;
}
The code is pretty long. Is there a shorter way to write it?
If I type in 33 the output will be "threethree". Could anyone give me suggestions how can i modify my code not to do that?
note: I am also not allowed to use functions.
You can use a variable to remember last input and compare, so that you will not print continuous char.
#include <stdio.h>
int main()
{
int c;
char* arr[4] = {"zero", "one", "two","three"};
int i;
char last_input = '9';
while ((c = getchar ()) != EOF)
{
if(c != last_input && '0' <= c && c <= '3') {
last_input = c;
int index = c - '0';
char* str = arr[index];
for (i = 0; str[i] != '\0'; i++) {
putchar(str[i]);
}
}
else{
putchar(c);
}
}
return 0;
}
You can compress your if statements using one if condition like this :
#include <stdio.h>
int main()
{
int c;
char* arr[4] = {"zero", "one", "two","three"};
int i;
while ((c = getchar ()) != EOF) {
int k = c-'0';
if(k>=0 && k<=3) {
char* str = arr[k];
for (i= 0; str[i] != '\0';i++) {
putchar(str[i]);
}
}
else {
putchar(c);
}
}
return 0;
}
Here is the simple approach to the same task. I tried to explain the logic in the comments.
int main(void) {
char *arr[11] = {"zero", "one", "two","three","four","five","six","seven","eight","Nine","Ten"};
int *input = malloc(sizeof(*input))/*1st time 4 byte */ , row = 1;
while( (input[row-1] = getchar())!=EOF ) {
if(input[row-1]==10) /* if ENTER key is presed */
break;
input[row-1] = input[row-1] - 48;/* convert it */
printf("%s ",arr[ input[row-1]%10 ]);/* its simple, just think on it */
row++;
input = realloc(input,row * sizeof(*input));/* reallocate based on number of input */
}
/* free dynamically allocated memory #TODO*/
return 0;
}
I just given hint, make it generic like write the condition if input is less than zero etc. I hope it helps.
Here my code using loop to shorten your code.
#include <stdio.h>
int main()
{
int c;
char* arr[4] = {"zero", "one", "two","three"};
int i, j;
while ((c = getchar ()) != EOF)
{
for(j = 0; j < 4; j++)
{
if(c == j + '0')
{
char* str = arr[j];
for (i = 0; str[i] != '\0'; i++)
{
putchar(str[i]);
}
j = 10; // just to detect processed character
break;
}
}
if(j != 10)
{
putchar(c);
}
}
return 0;
}

C histogram of words printing problems

I have this code, what i want it to do is print the string that represents the word, and print the number of times it occurred in the file, instead it outprints something liek this: (a load of blank space) and then this number -1076720020, which i have no idea where it came from, how would i go about fixing this?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
struct podatki {
char beseda[1000];
int frekvenca;
};
void zamenjaj(char *str1, char *str2) {
char *beseda2 = (char *)malloc((strlen(str1) + 1) * sizeof(char));
strcpy(beseda2, str1);
strcpy(str1, str2);
strcpy(str2, beseda2);
free(beseda2);
}
int posodobi(struct podatki s[], const char unit[], int count) {
int i =0;
for (i = 0; i < count; i++) {
if (strcmp(s[i].beseda, unit) == 0) {
s[i].frekvenca++;
return count;
}
}
strcpy(s[count].beseda, unit);
s[count].frekvenca++;
return (count + 1);
}
int main() {
int stBes;
scanf("%d", &stBes);
//zacetne deklaracije
struct podatki s[1000];
char string[1000], unit[2000], c;
int i = 0;
int frekvenca = 0;
int j = 0;
int count = 0;
int num = 0;
//branje
for (i = 0; i < 1000; i++) {
s[i].frekvenca = 0;
}
i = 0;
do {
fflush(stdin);
c = getchar();
string[i++] = c;
} while (c != '\n');
//pretvori v majhne crke
char *p;
for (p = string; *p != '\0'; ++p) {
*p = tolower(*p);
}
string[i - 1] = '\0';
for (i = 0; i < strlen(string); i++) {
while (i < strlen(string) && string[i] != ' ' && !ispunct(string[i])) {
unit[j++] = string[i++];
}
if (j != 0) {
unit[j] = '\0';
count = posodobi(s, unit, count);
j = 0;
}
}
int a;
for (i = 0; i < count; ++i) {
for (j = i + 1; j < count; ++j) {
if (s[i].frekvenca < s[j].frekvenca) {
a = s[i].frekvenca;
s[i].frekvenca = s[j].frekvenca;
s[j].frekvenca = a;
zamenjaj(s[i].beseda, s[j].beseda);
}
}
}
for (i = 0; i < count; i++) {
for (j = 1; j < count; j++) {
if (s[i].frekvenca == s[j].frekvenca){
if (strcmp(s[i].beseda, s[j].beseda) < 0) {
a = s[i].frekvenca;
s[i].frekvenca = s[j].frekvenca;
s[j].frekvenca = a;
zamenjaj(s[i].beseda, s[j].beseda);
}
}
}
}
//printanje
for (i = 0; i < stBes; i++) {
printf("%s\t %d\n", s[i].beseda, s[i].beseda);
if (s[i].frekvenca > 1) {
num++;
}
}
return 0;
}
The problem is that you convert the string to lower case before nul terminating it.
Here
i = 0;
do {
fflush(stdin);
c = getchar();
string[i++] = c;
} while (c != '\n');
/* Goes here <---------------------+ */
/* | */
//pretvori v majhne crke | */
char *p; /* | */
for (p = string; *p != '\0'; ++p) {/* | */
*p = tolower(*p);/* | */
} /* | */
/* | */
string[i - 1] = '\0'; /* ---------------------+ */
You should also remove the fflush(stdin) and instead use getchar() to fetch the white space characters ignored by the previous scanf(), and please use scanf() correctly and check it's returned value.

Resources