Number of smallest length of string, in C - c

I want to make a program, which prints the number of smallest length of string. I have a file of words, which I open from stdin and save it to buffer.
My code so far prints the length of each word. But I can't figure out how to compare these numbers.
For example in file are:
Hello
Hi
My program does:
6
3
The output should be:
3
I can't figure ou how to continue. Do you have any advice?
#include <stdio.h>
int min_stat(char str[])
{
int min=0;
for(int i=0; str[i] != '\0'; i++)
{
min++;
}
return min;
}
int main(int argc, char *argv[])
{
if(argc < 1){
fprintf(stderr,"Error\n");
return 1;
}
char param = argv[1][0];
int val=100;
char buffer[val];
if(param == '1')
{
while(fgets(buffer, val, stdin) != NULL)
{
int a = min_stat(buffer);
printf("%d\n", a);
}
}
return 0;
}

You need to save the minimum lenght of the string somewhere and update it if a shorter string is detected. Your min_stat function returns the number of characters of the string.
I would use something like this:
#define MAX_LENGHT 1000
int main(int argc, char *argv[])
{
if(argc < 1){
fprintf(stderr,"Error\n");
return 1;
}
char param = argv[1][0];
int val=100;
char buffer[val];
/* the maximum possible lenght */
int min_lenght = MAX_LENGHT;
if(param == '1')
{
while(fgets(buffer, val, stdin) != NULL)
{
int a = min_stat(buffer);
/* update the mimimum lenght if it is smaller
than the current value */
if (a < min_lenght) {
min_lenght = a;
}
printf("%d\n", a);
}
}
/* print the minimum lenght */
printf("Minimum: %d\n", min_lenght);
return 0;
}
You should not use a variable to initialize the char array, because you are using Variable Lenght Arrays (VLA) and not static arrays. If you are learning c you should use static arrays and so:
char buffer[MAX_LENGHT];
where MAX_LENGHT is a constant or a pre-processor definition.

Related

Removing a char at index i in a string and make new strings C

Suppose we have a string called StringA[] = "ABCD". you have to delete only one char and make new strings like "BCD, ACD,ABD,ABC". is this case you need to determine how many time the strings appears in a other string StringB[];
the length of StringA is allways less than StringB's but they both needs to have a length of less than 100 and bigger than 2
Following is my attempt. I make a pointer so save the value of S and then do operations on it and when one iteration is done I reassign it to S again. but the solution it provides is wrong. for instance for the case above the type2 variable needs to be 4 but it gives 1. I guess the problem is in using memmove function. I would appreciate any help.
#include <stdio.h>
#include <string.h>
int CheckOccurence(size_t len, char* stringA, char* stringB);
int type1, type2, type3;
int main(int argc, char **argv)
{
char L[100];
char S[100];
char *holdChar;
while(scanf("%s%s", S,L) == 2){
size_t lenS = strlen(S);
size_t lenL = strlen(L);
int minLengthSat = (lenS >= 2 && lenL >= 2);
int maxLengthSat = (lenS <= 100 && lenL <= 100);
int isSless = lenS <= lenL;
holdChar = S;
if(minLengthSat && maxLengthSat && isSless){
type1 = CheckOccurence(lenS,&S,&L);
for (int i =0; holdChar[i] !='\0'; i++ ){
//holdChar[i] = holdChar[i+1];
memmove(&holdChar[i], &holdChar[i+1], strlen(holdChar) -i);
type2 += CheckOccurence(lenS,holdChar,&L);
holdChar = S;
}
printf("%d%d\n",type1,type2);
printf("%s\n",S);
}else{
printf("Condition not fulfilled. Try again!\n");
}
}
return 0;
}
int CheckOccurence(size_t len, char* stringA, char* stringB){
int count = 0;
while(stringB = strstr(stringB, stringA))
{
count++;
stringB+=len;
}
return count;
}

C: search for non-number-character in array

I am building a C program which gets a .txt file as an argument. Inside the .txt there are rows of integer numbers, with a space between them, like this:
1 2 3 4
5 6 7 8
...
I am supposed to find out, if a non-integer-character shows up inside the .txt file, like this:
1 2 a 4
...
Since there is no instanceof operator in C, I use an array which contains the numbers from 0-9 and check each character of the .txt-file, if it is either a space or an integer. If it is neither, the program is supposed to exit.
If there are no problems in the file, the program calculates a median and prints the line to stdout.
This is my code:
#include <stdio.h>
#include <ctype.h>
int arrayContains(char value);
int main(int argc, char **argv) {
const int LINESIZE = 255;
if (argc != 2) {
printf("wrong args!");
return -1;
}
char *command1 = argv[1];
FILE *handle = fopen(command1, "r");
if (!handle) {
printf("file not found!");
return -1;
}
int count = 0;
int sum = 0;
int median;
char string[LINESIZE];
while (fgets(string, LINESIZE, handle) != NULL) {
for (int i = 0; i <= sizeof(string) / sizeof(string[0]) - 1; i++) {
printf("%c", string[i]);
if (string[i] == ' ') {
i++;
}
else if (arrayContains(string[i]) == 0) {
count++;
sum += (int)string[i];
}
else {
printf("non-integer-character found!\n");
return -1;
}
}
median = sum / count;
printf("%s\n", string);
printf("%d\n", median);
}
}
int arrayContains(char value) {
const char numbers[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
for (int i = 0; i <= 9; i++) {
if (numbers[i] == value) {
return 0;
}
}
return -1;
}
Now the output of the program is always the first number of the txt-file and immediately after that: "non-integer-character found!".
Which tells me that the comparison between the element of the string from gets() and an element from the constant "numbers" array inside the arrayContains() function, will always result in a return of -1 from the arrayContains() function.
What am I doing wrong?
You should really check out isdigit C function!
#include <ctype.h>
int hasDigit(const char *s)
{
while (*s) {
if (isdigit(*s++) == 0) return 0;
}
return 1;
}
Code above returns 1 on empty string. Watch out! You can use my function instead of your arrayContains. If you want to use your routine, please check out my "version":
int arrayContains(char value) {
return isdigit(value)?0:-1;
}
There are several problems with your code.
This bit matches a space, but will result in you skipping the following character because your loop will also do i++.
if (string[i] == ' ') {
i++;
}
This is not the right way to turn a digit into a number. What you're getting here is the ASCII value of the character rather than the value of the digit. So for example if you have a '1' you're adding 49 to sum rather than 1.
sum += (int)string[i];
As discussed elsewhere, you're better off using isdigit() to identify if you've got a digit character. You can also use isspace() to test to see if you have a space or '\n' character (it covers all whitespace). Which would make your loop statement a lot less complicated as you can process the whole string and easily handle lines that are longer than the size of your buffer.
This code corrects the problems you have
while (fgets(string, LINESIZE, handle) != NULL) {
for (char *pos=string; *pos!='\0'; pos++) {
printf("%c", *pos);
if (isdigit(*pos)) {
count++;
sum += *pos-'0';
} elseif(!isspace(*pos)) {
printf("non-integer-character found!\n");
return -1;
}
}
median = sum / count;
printf("%s\n", string);
printf("%d\n", median);
}
I seem to have solved it:
#include <stdio.h>
#include <ctype.h>
int arrayContains(char value);
int main(int argc, char **argv) {
const int LINESIZE = 255;
if (argc != 2) {
printf("wrong args!");
return -1;
}
char *command1 = argv[1];
FILE *handle = fopen(command1, "r");
if (!handle) {
printf("file not found!");
return -1;
}
int count = 0;
int sum = 0;
int median;
char string[LINESIZE];
while (fgets(string, LINESIZE, handle) != NULL) {
for (int i = 0; i <= sizeof(string) / sizeof(string[0]) - 1; i++) {
printf("%c\n", string[i]);
if (isspace(string[i]) == 0) {
i++;
}
else if (isdigit(string[i]) == 0) {
count++;
sum += (int)string[i];
}
else {
printf("non-integer-character found!\n");
return -1;
}
}
fgets(string, LINESIZE, handle);
}
median = sum / count;
printf("%s\n", string);
printf("%d\n", median);
}
it now kinda does the job as expected.
You use the operator sizeof() which won't return the length of the String but the memory size of the pointer (a size_t so 8 bytes).
I suggest you to use this for your for loop:
for (int i = 0; string[i] != '\0' && string[i] != '\n'; i++) {
...
}
String in C are just a part of memory, it's just like an array and the only way to get the length is to find the end ('\0')
I also suggest you to directly search into the ASCII table. Characters are just number between 0 and 127. Digits are between 48 and 57, a simple condition does the stuff !
if (string[i] <= 48 || string[i] >= 57) {
...
}

What's wrong with my Heap's Algorithm code?

My homework requires me to write a program that takes a string from the terminal (argc and argv) and print every possible permutation. I have tried to use Heap's Algorithm, but it doesn't seem to be working out. Below is my function.
char **getPermutation(char * in)
{
//n is the size of the input string.
int n = strlen(in);
int count[n];
int counter= 0;
char copy[n];
char **permutations = malloc(sizeof(char*)*(factorial(n)));
permutations[0] = in;
strcpy(in, copy);
counter++;
for( int i = 1; i < n;)
{
if (count[i] < i){
if (i%2==0){
swap(&in[0],&in[i]);
}
else
{
swap(&in[count[i]],&in[i]);
}
permutations[counter] = in;
strcpy(in, copy);
counter++;
count[i]++;
i = 1;
}
else
{
count[i] = 0;
i++;
}
}
return permutations;
}
The function must return the pointer to the character pointer as specified by the instructions. That's also why there are so many variables (although, I'm not really sure what to do with the copy of the string. I'm fairly sure I need it). Testing shows that the program will loop, often too much and eventually hit a seg fault. It doesn't seem like the swapped strings make it into the returned array on top of that.
Below is a rework of your code with cleaned up memory allocation and it addresses some problems mentioned in the above comments. Additionally, you have a bug in your algorithm, this statement strcpy(in, copy); keeps you from getting all the permutations (causes repeats instead.) This code works but isn't finished, it can use more error checking and other finishing touches:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned int factorial(unsigned int n)
{
/* ... */
}
void swap(char *a, char *b)
{
/* ... */
}
char **getPermutations(const char *input)
{
char *string = strdup(input);
size_t length = strlen(string);
char **permutations = calloc(factorial(length), sizeof(char *));
int *counts = calloc(length, sizeof(int)); // point to array of ints all initialized to 0
int counter = 0;
permutations[counter++] = strdup(string);
for (size_t i = 1; i < length;)
{
if (counts[i] < i)
{
if (i % 2 == 0)
{
swap(&string[0], &string[i]);
}
else
{
swap(&string[counts[i]], &string[i]);
}
permutations[counter++] = strdup(string);
counts[i]++;
i = 1;
}
else
{
counts[i++] = 0;
}
}
free(counts);
free(string);
return permutations;
}
int main(int argc, char *argv[])
{
char *string = argv[1];
char **permutations = getPermutations(string);
unsigned int total = factorial(strlen(string));
for (unsigned int i = 0; i < total; i++)
{
printf("%s\n", permutations[i]);
}
free(permutations);
return 0;
}
OUTPUT
> ./a.out abc
abc
bac
cab
acb
bca
cba
>

pointers to an array only print the first character?

Just started learning c. I'm confused with the pointers and arrays.
This is my main function.
int next_statement(char *a, int n);
void consume_char(char c);
int var_lib_check(char type,char var);
int
main(int argc, char *argv[]) {
char statement[MAX_LINE];
int statement_len;
char type[MAX_LINE];
char var[MAX_LINE];
/* Print the output header comment */
printf(OUTPUT_HEADER, argv[0]);
/* Loop through statements read on stdin */
while ((statement_len = next_statement(statement,MAX_LINE)) > 0) {
printf("%s\n",statement);
sscanf(statement,"%s %s",type,var);
var_lib_check(*type,*var);
}
return 0;
int
var_lib_check(char type,char var){
char var_library[MAX_VARS][MAX_LINE];
char new_var[MAX_LINE];
int num_of_var;
int z;
num_of_var = 0;
printf("%s and %s",&type,&var);
if (strcmp(&type,DOUBLE_TYPE)==0||strcmp(&type,INT_TYPE)==0||
strcmp(&type,RTRN_TYPE)==0){
for (z= 0; z < num_of_var; z++){
if (strcmp(var_library[z],&var) == 0){
sprintf(new_var,"x%d",z);
printf("%s %s",&type,new_var);
return z;
}
}
strcpy(var_library[num_of_var],&var);
num_of_var += 1;
sprintf(new_var,"%x%d",num_of_var);
printf("%s %s",&type,new_var);
}
return num_of_var;
}
This program reads the input and if it is either int or double ... it would replace it to be for e.g. int x0.
Why does it only print the first letter of the type and variable when it runs the function when it should print the whole string?
int
next_statement(char *a, int n) {
int c, i;
for (i=0; i < n && (c = getchar()) != EOF; i++) {
if (c == CHAR_SEMI) {
consume_char('\n');
break;
}
a[i] = c;
}
if (c == CHAR_SEMI) {
a[i] = '\0';
return i; /* index when ; was read, so the length of saved. */
}
else if (i >= n) {
printf("%s Line too long.\n", ERROR_PREFIX);
exit(EXIT_FAILURE);
}
return 0;
}
/* reads one char from stdin and errors if it is not what was
* expected, thereby "consuming" the given char.
*/
void
consume_char(char c) {
int x;
if ((x=getchar()) != c) {
printf("%s expected '%c' found '%c'.\n", ERROR_PREFIX, c, x);
exit(EXIT_FAILURE);
}
return;
You have the function definition as
int var_lib_check(char type,char var){
and you call it as
var_lib_check(*type,*var);
By doing this, you are only passing one character, and not the entire string to it.
You should change your function to
int var_lib_check(char *type,char *var)
and call it as
var_lib_check(type,var);
Now, you are passing the string to it, and you can work on it like a pointer.
It's because you are passing only the first char to var_lib_check(). You have to pass the array, so first fix this
var_lib_check(*type,*var);
make it
var_lib_check(type,var);
then fix the var_lib_check() function
int
var_lib_check(char *type, char *var)
{
char var_library[MAX_VARS][MAX_LINE];
char new_var[MAX_LINE];
int num_of_var;
int z;
num_of_var = 0;
printf("%s and %s", type, var); /* remove the & */
if (strcmp(type, DOUBLE_TYPE) == 0 || strcmp(type, INT_TYPE) == 0 || \
strcmp(type, RTRN_TYPE)==0)
{
for (z = 0 ; z < num_of_var ; z++)
{
if (strcmp(var_library[z], var) == 0)
{
sprintf(new_var, "x%d", z);
printf("%s %s", type, new_var);
return z;
}
}
strcpy(var_library[num_of_var], var);
num_of_var += 1;
sprintf(new_var, "%x%d", num_of_var);
printf("%s %s", type, new_var);
}
return num_of_var;
}
Most of the code invokes undefined behavior, because you pass the address to a char where a pointer to a string is expected.
A string consists of a sequence of non-nul bytes followed by a nul byte, since you where passing the address to just one byte, the functions, namely printf() and strcmp() where reading past the value of the passed variable.

Specified letter count with recursion

I'm trying to write a recursive algorithm that obtains to count specified a letter by user. But, I'm stuck in two cases. First, I think I must get 2 as result, I can't. Second, If there is no limit key, for instance the limit character specified as z by user , how the characters can be scanned up to end character here g ? The problem little bit complicated for me. I need your advices and ideas. Thank you all appreciated answers.
example string is: how are you i am testing
another examples:
#include <stdio.h>
int lettercount(char* str, char key, char limit);
int main(){
char test[]="how are you i am testing";
int num;
num=lettercount(test,'a','t');
printf("%d",num);
return 0;
}
int lettercount(char* str, char key, char limit)
{
int count = 0;
if(str[0] == limit)
{
return 0;
}
else if(str[0] == key)
{
lettercount(&str[1], key, limit);
count++;
}
else
lettercount(&str[1], key, limit);
return count;
}
as the code is unwinding from the recursion(s)
it needs to accumulate the count
the following code should work for your needs.
Note: this returns 0 if key and limit are the same char
int lettercount(char* str, char key, char limit)
{
int count = 0;
if(str[0] == limit)
{
return 0;
}
// implied else, more char in string to check
if(str[0] == key)
{
count++;
}
count += lettercount(&str[1], key, limit);
return count;
} // end function: lettercount
With a recursive function, you need 3 things. (1) set up in the function that prepares for the next call; (2) a recursive call; and (3) a way to terminate the recursion. Here is one approach. Note: the version in the code below is a long version for readability, a short version is included at the end:
#include <stdio.h>
/* recursively find the number of occurrences
of 'c' in 's' (n is provided as '0')
*/
int countchar (char *s, char c, int n)
{
char *p = s;
if (!*p)
return n;
if (*p == c)
n = countchar (p+1, c, n+1);
else
n = countchar (p+1, c, n);
return n;
}
int main (int argc, char **argv) {
if (argc < 3) {
fprintf (stderr, "\n error: insufficient input. Usage: %s <string> <char>\n\n", argv[0]);
return 1;
}
int count = countchar (argv[1], *argv[2], 0);
printf ("\n There are '%d' '%c's in: %s\n\n", count, *argv[2], argv[1]);
return 0;
}
output:
$ ./bin/rec_c_in_s "strings of s'es for summing" s
There are '5' 's's in: strings of s'es for summing
You can make the function shorter, but slightly less readable with:
int countchar (char *s, char c, int n)
{
char *p = s;
if (!*p) return n;
return countchar (p+1, c, (*p == c) ? n+1 : n);
}

Resources