c - printing the longest string and string length? - c

I'm new to c programming, and i'm suppose to write a code to find the longest string and it's string length from an array of strings. This is my code so far.
#include <stdio.h>
#include <string.h>
#define N 20
char *longestStrInAr(char str[N][40], int size, int *length);
int main()
{
int i, size, length;
char str[N][40], first[40], last[40], *p;
char dummychar;
printf("Enter array size: \n");
scanf("%d", &size);
scanf("%c", &dummychar);
for (i=0; i<size; i++) {
printf("Enter string %d: \n", i+1);
gets(str[i]);
}
p = longestStrInAr(str, size, &length);
printf("longest: %s \nlength: %d\n", p, length);
return 0;
}
char *longestStrInAr(char str[N][40], int size, int *length)
{
int i,j=0;
int len = 0;
*length = 0;
char word[N];
for(i=0;i<size;i++){
while(str[i][j]!='\0'){
len++;
j++;
}
if(*length<len){
*length = len;
strcpy(word,str[i]);
}
}
return word;
}
The main{} is a given function, and the code under *longestStrInAr is the one im suppose to write. However, my current code is only able to give me the longest string length, and prints out (null) instead of the longest string.
my output

Problems I see:
Problem 1
Don't use gets. It's a security hole. Use fgets instead.
fgets(str[i], 40, stdin);
Problem 2
You are using incorrect size for word. It needs to be of size 40.
char word[40];
Problem 3
You are returning a pointer to the first element of word from
longestStrInArr. However, that memory is invalid once the function returns. Hence, your program has undefined behavior.
You can fix it by returning the index of the longest string in str or by providing an input argument long enough to hold the longest string.
size_t longestStrInAr(char str[N][40], int size, int *length)
{
size_t index = 0
size_t i,j=0;
int len = 0;
*length = 0;
for(i=0;i<size;i++){
while(str[i][j]!='\0'){
len++;
j++;
}
if(*length<len){
*length = len;
index = i;
}
}
return index;
}
and then use it as:
size_t index = longestStrInAr(str, size, &length);
printf("longest: %s \nlength: %d\n", str[index], length);

You copy the string into local variable and then return pointer to it. But after returning, the variable is no longer valid. That is undefined behavior and "anything" can happen. In this case it seems some optimization or a debug helper turns it to null.
Instead just keep a pointer to the longest string in the str array, don't copy anything and return that pointer. Alternatively, if you want to simplify it, return the i index of the longest string.

Related

My ouput for C differs from compiler to compiler

I am writing a function longestStrInAr() that takes in an array of strings str and size (>0) as parameters, and returns the longest string and also the length of the longest string.
If two or more strings have the same longest string length, then the first appeared string will be
returned to the calling function.
This is the main function:
#include <stdio.h>
#include <string.h>
#define N 20
char *longestStrInAr(char str[N][40], int size, int *length);
int main()
{
int i, size, length;
char str[N][40], first[40], last[40], *p, *result;
char dummychar;
printf("Enter array size: \n");
scanf("%d", &size);
scanf("%c", &dummychar);
for (i=0; i<size; i++) {
printf("Enter string %d: \n", i+1);
fgets(str[i], 40, stdin);
if (p=strchr(str[i],'\n')) *p = '\0';
}
result = longestStrInAr(str, size, &length);
printf("longest: %s \nlength: %d\n", result, length);
return 0;
}
This is the function I have to write:
char *longestStrInAr(char str[N][40], int size, int *length)
{
int i,j, len;
*length =0;
char *longstr;
for (i = 0; i< size; i++){
j = 0;
len = 0;
while (str[i][j]!='\0'){
len++;
j++;
if (len > *length){
*length = len;
longstr = str[i];
}
}
}
return longstr;
}
My test input is
Enter array size:
4
Enter string 1:
Kenny
Enter string 2:
Mary
Enter string 3:
Peter
Enter string 4:
Sun
In XCode, I am able to receive the correct output:
longest: Kenny
length: 5
But using 2 different online compilers, I get the output below on both occasions:
longest: Kenny
length: 6
Why does my length differ?
Thank you.
probably one of them is a windows based compiler.
there "\n" is tread as two characters \r and \n
\r is called as carriage return
\n is called as line feed.
with this you get a byte extra there.

Defining size for string using a variable not working properly in for loop in C

I'm trying to reverse the string input entered by user, the problem here is in function *rev, when I use size = strlen(STR); to get the length of the string and pass it into the size of the revS[size] the program outputs some garbage value for reverse string! if I pass some value instead if size in revS[10] and run the program it works as expected. I Have checked the value of size as
printf("\nlength of string is: %d\n",size);
and it gives the correct value. I'm not getting where is it going wrong!
#include<stdio.h>
#include<string.h>
char *rev(char *);
int main()
{
char string[100];
printf("Enter the string to reverse: ");
scanf("%s", string);
printf("You entered string : %s\n Reversed string is: %s", string, rev(string));
}
char *rev(char *STR)
{
int size, i, j = 0;
size = strlen(STR);
printf("\nlength of string is: %d\n", size);
char revS[size];
for(i = size-1; i >= 0; i--)
{
revS[j] = STR[i];
j = j + 1;
}
revS[j] = '\0';
return (revS);
}
OUTPUT:
Enter the string to reverse: mahaveer
length of string is: 8
You entered string : mahaveer
Reversed string is: ╚²b
--------------------------------
Process exited after 28.7 seconds with return value 0
Press any key to continue . . .
The issue is that your reversed string is allocated on the stack rather than the heap. When your rev function returns, all of the variables in that scope will be garbage collected. You can use malloc() to allocate memory dynamically on the heap. Note that the caller is responsible for calling free() on the string to avoid a memory leak.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *rev(char *);
int main() {
char string[100];
printf("Enter the string to reverse: ");
scanf("%s", string);
char *r = rev(string);
printf("You entered string: %s\nReversed string is: %s\n", string, r);
free(r);
}
char *rev(char *str) {
int i, j;
int size = strlen(str);
char *rev = malloc(sizeof(*rev) * (size + 1));
for (i = size - 1, j = 0; i >= 0; i--, j++) {
rev[j] = str[i];
}
rev[size] = '\0';
return rev;
}
Note that this code is susceptible to buffer overflows.
You have tho major UBs here. First you allocate local storage array which is not available after the function return. The second one - the size is too small to accomodate the string plus terminating zero

function to get words and put them in array

I need to write a C function that gets from the user the number of the words that he wants to enter, then the function has to scan the word from the user and but them in the array.
For example:
Program:
number of words:
User:
3
hi
my
name
(between every word there is enter) then the function has to put these words in
string array (the size of the array must be defined by malloc and the max size of the string is 100 (could be less)).
int main()
{
int n;
printf("Please enter the number of words: \n");
if (scanf("%d",&n)!=1)
return 0;
char *name;
name = malloc((sizeof(char)*100*n));
int c;
int i;
int m;
for (i = 0; i < n && ((c=getchar()) != EOF );i++)
{
name[i] = c;
}
finds_themin(&name, m); //I know this work
return 0;
}
You need to setup a pointer to pointer.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
char **s;
int n;
char buffer[64];
fgets(buffer,64,stdin);
n=strtol(buffer,NULL,10);// I avoid using scanf
s=(char **)malloc(sizeof(char*)*n);// you need to declare a pointer to pointer
/*
'PtP s' would look like this:
s[0]=a char pointer so this will point to an individual string
s[1]=a char pointer so this will point to an individual string
s[2]=a char pointer so this will point to an individual string
....
so you need to allocate memory for each pointer within s.
*/
int i;
for(i=0;i<n;i++){
s[i]=(char*)malloc(sizeof(char)*100);// length of each string is 100 in this case
}
for(i=0;i<n;i++){
fgets(s[i],100,stdin);
if(strlen(s[i])>=1){// to avoid undefined behavior in case of null byte input
if(s[i][strlen(s[i])-1]=='\n'){ // fgets also puts that newline character if the string is smaller than from max length,
s[i][strlen(s[i])-1]='\0'; // just removing that newline feed from each string
}
else{
while((getchar())!='\n'); //if the string in the command line was more than 100 chars you need to remove the remaining chars for next fgets
}
}
}
for(i=0;i<n;i++){
printf("\n%s",s[i]);
}
for(i=0;i<n;i++){
free(s[i]); //avoiding leaks
}
free(s);
}
As you need to store an array of strings you need an array of char* or char** to point each string (char array).
char **name;
name = malloc(n); // to store n strings.
Then in the loop use fgets to read the input as a line. Also, you need to allocate the memory for each new char array.
fflush(stdin);
for (i = 0; i < n; i++) {
name[i] = malloc(100); // allocating memory for string.
fgets (name[i], 100, stdin); // 100 is the max len
}
You can then simply iterate over the char** array, the ith index will point to the ith string.
for (i = 0; i < n; i++) {
// printf("%s", name[i]);
}

Would does this function which converts a char array to an int array not work?

This program is supposed to convert the array of chars (string) into an array of ints by subtracting 97 from their ascii value (the input should be lower case cause a has an ascii value of 97). So if i enter the string abcd i should get 0123 but instead I somehow get this: 012134513789. I can't figure out where the problem is.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void userEnter(int*pattern, int n);
int main(void)
{
int n, i;
printf("What is the length of the array: ");
scanf("%d",&n);
int pattern[n];
printf("Enter the char array: ");
userEnter(pattern, n);
printf("The int array is: ");
for(i=0;i<n;i++)
{
printf("%d",pattern[i]);
}
printf("\n");
}
void userEnter(int*pattern, int n)
{
char input[n];
scanf("%s", input);
int i;
for(i = 0; i < n-1; i++)
{
pattern[i] = input[i]-97;
}
}
char input[n];
scanf("%s", &input);
should be
char input[n+1];
scanf("%s", input);
input is equivalent to &input[0]
You should also exit the for loop in userEnter when you encounter the nul character that ends the user-entered string. e.g. with something like
char* p = input;
while (*p != '\0') {
*pattern = (*p) - 'a';
p++;
pattern++;
}
As KingsIndian points out, you also need to increase the size of your input buffer. At present, you overflow that buffer and overwrite the loop counter i;
The length parameter n includes one character for null as well. So, if you input length for n 4 then you can only input 3 characters, for example abc because the 4th is for the null.
So you should change the declaration accordingly:
Change:
char input[n];
to:
char input[n+1];
Note that variable length arrays are allowed only since C99.

Problems with simple c task

So after a few years of inactivity after studying at uni, I'm trying to build up my c experience with a simple string reverser.
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
*
*/
int main(int argc, char** argv) {
reverser();
return(0);
}
int reverser(){
printf("Please enter a String: ");
//return (0);
int len;
char input[10];
scanf("%s",&input);
int quit = strcmp(input,"quit");
if(quit == 0){
printf("%s\n","Program quitting");
return(0);
}
len = strlen(input);
printf("%i\n",len);
char reversed[len];
int count = 0;
while (count <= (len-1)){
//printf("%i\n",(len-count));
reversed[count] = input[(len-1)-count];
count++;
}
//printf("%s\n",input);
printf(reversed);
printf("\n");
reverser();
}
When I input "hello", you would expect "olleh" as the response, but I get "olleh:$a ca&#",
How do I just get the string input reversed and returned?
Bombalur
Add a '\0' at the end of the array. (as in, copy only chars until you reach '\0' - which is the point at array[strlen(array)], then when you're done, add a '\0' at the next character)
Strings are conventionally terminated by a zero byte. So it should be
char reversed[len+1];
And you should clear the last byte
reversed[len] = (char)0;
you forgot the \0 at the end of the string
This is because you are creating an array with size 10. When you take in some data into it (using scanf) and the array is not filled up completely, the printf from this array will give junk values in the memory. You should iterate for the length of the input by checking \n.
must have a size + 1 to string length so that you can have a \0 at the end of string that will solve your problem
The following is a (simple and minimal implementation of) string reverse program (obviously, error conditions, corner cases, blank spaces, wider character sets, etc has not been considered).
#include <stdio.h>
int strlen(char *s)
{
char *p = s;
while (*p)
p++;
return p - s;
}
char * strrev(char a[])
{
int i, j;
char temp;
for (i=0, j=strlen(a)-1 ; i<j ; i++, j--) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
return a;
}
int main()
{
char str[100];
printf("Enter string: ");
scanf("%s", str);
printf("The reverse is %s \n", strrev(str));
return 0;
}
Hope this helps!

Resources