Use strcpy() or strncpy() for array of strings? - c

I'm struggling to copy a string within an array at a given index to another array of strings, any suggestions? When trying to print out the value of tempVal at any given index, it doesn't return anything.
#include <stdio.h>
#include <string.h>
int main(void) {
const int NUM_VALS = 20;
int i;
int matchCount = 0;
int actualInput;
scanf("%d", &actualInput);
char userString[actualInput][NUM_VALS];
char tempVal[actualInput][NUM_VALS];
for (i = 0; i < actualInput; ++i) {
scanf("%s", userString[i]);
// printf("%s", userString[i]);
strncpy(userString[i], tempVal[i], strlen(userString[i])); // < -- Not sure how to make work
printf("%s", tempVal[i]); // <-- Doesn't output anything?
}
return 0;
}

use the function which will limit the number of chars read and place the terminatins zero as well
for (int i = 0; i < actualInput; ++i) {
fgets(userString[i], NUM_VALS, stdin);
strcpy(tempVal[i], userString[i]); // < -- Not sure how to make work
printf("%s\n", tempVal[i]); // <-- Doesn't output anything?
}

It is no wonder why you got no appropriate output because with the provided code you high-probably will get a Segmentation fault. Beside this, there are several issues in the code. To explain them all and also answer the heading question would explode the frame. You can see how I corrected the code in my manner below.
char* strcpy ( char* destination, const char* source )
strcpy is a potential risk for causing buffer overflow if the destination char buffer is not large enough to hold the string to be copied by source. This in your case okay, because each buffers, userString[i] and tempVal[i], have the same capacity (amount of char elements), but if the code changes it could be harmful.
Note that you also should limit the amount of input characters when you catch the string from stdin. For this reason, fgets() is safer than scanf(), since it explicitly requires a maximum amount of characters to read.
char* strncpy ( char* destination, const char* source, size_t num );
strncpy fails to append a terminating null character if the first num characters of the source string do not contain a terminating \0.
Rather use snprintf() which is safe to 1. proofs the size of the destination buffer and limits the amount of characters to read and 2. always appends a null character (assuming the scan process was successful and no errors occurred):
#include <stdio.h>
#include <string.h>
int main(void) {
const int NUM_VALS = 20;
int i;
int s_num;
printf("Enter number of strings in array: ");
scanf("%d", &s_num);
getchar();
char userString[s_num][NUM_VALS];
char tempVal[s_num][NUM_VALS];
for (i = 0; i < s_num; ++i) {
printf("Enter string at userString[%d]: ",i);
if(fgets(userString[i],NUM_VALS, stdin) == NULL)
{
// error handling
if(ferror(stdin))
{
// handle I/O error.
}
else if(feof(stdin))
{
// end of file is reached.
}
}
else
userString[i][strcspn(userString[i], "\n")] = 0;
//printf("%s", userString[i]);
}
printf("\n");
for (i = 0; i < s_num; ++i) {
if(snprintf(tempVal[i], sizeof(tempVal[i]), "%s", userString[i]) < 0)
{
// error handling
fprintf(stderr,"Encoding error occurred!");
}
printf("tempValue[%d]: %s\n", i, tempVal[i]);
}
return 0;
}
Output at a test run:
Enter number of strings in array: 3
Enter string at userString[0]: hello
Enter string at userString[1]: world
Enter string at userString[2]: test
tempValue[0]: hello
tempValue[1]: world
tempValue[2]: test

Sorry guys,
I am taking a class and new to C. I was able to figure out how to solve my problem. I appreciate the suggestions for fixing the code, unfortunately they are beyond the scope of what I have learned in my intro course. I had to find word frequencies using a string array and for loops. Here is the complete working code:
#include <stdio.h>
#include <string.h>
int main(void) {
const int NUM_VALS = 20;
int i;
int j;
int matchCount = 0;
int actualInput;
scanf("%d", &actualInput);
char userString[actualInput][NUM_VALS];
char tempVal[actualInput][NUM_VALS];
for (i = 0; i < actualInput; ++i) {
scanf("%s", userString[i]);
strcpy(tempVal[i], userString[i]);
// printf("%s\n", userString[i]);
// printf("%s\n", tempVal[i]);
}
for (i = 0; i < actualInput; ++i) {
matchCount = 0;
for (j = 0; j < actualInput; ++j) {
if (strcmp(userString[i], tempVal[j]) == 0) {
matchCount++;
}
}
printf("%s %d\n", userString[i], matchCount);
}
return 0;
}

Related

I have problem with reading input with blank spaces

I made this function to get input:
void entrada_dados(Time* time, int i){
scanf("%s %d %d", time[i].nome, &time[i].gols_marcados, &time[i].gols_sofridos);
};
The input is in this form:
2
Campinense
23
12
ABC
30
13
The main is:
int main(void) {
int n = 0;
scanf("%d", &n);
for(int i = 0; i < n; i++){
entrada_dados(time, i);
}
....
My problem is when the team name have some space like to "São Paulo". I have tried some forms to solve, but no one solved my problem.
I tried:
void entrada_dados(Time* time, int i){
fscanf(stdin, "%[^\n] %d %d", time[i].nome, &time[i].gols_marcados, &time[i].gols_sofridos);
};
and:
void entrada_dados(Time* time, int i){
fgets(time[i].nome, 100, stdin);
scanf("%d", &time[i].gols_marcados);
scanf("%d", &time[i].gols_sofridos);
}
but in the first case the output have nothing, and second case the output miss some cases. Someone can help me to understand this problem?
Edit 1:
The definition of .name is:
typedef struct Time{
char nome[100];
int gols_marcados;
int gols_sofridos;
} Time;
Edit 2:
Solution:
One way to solve it:
Try two fscanfs fscanf(stdin, " %[^\n]", time[i].nome);
fscanf(stdin, "%d %d", &time[i].gols_marcados, &time[i].gols_sofridos);
Thank you guys.
Because you have to handle strings with spaces, it's better to use fgets for those.
But mixing fgets and scanf doesn't work too well. We can replace scanf with fgets followed by sscanf.
To decode numbers, we can use strtol or sscanf
We take advantage of the fact that each element/member of Time appears on a separate line in the input file, so we can do fgets for every line. This simplifies the code and makes error checking easier.
Here is the refactored code. It is annotated.
I didn't do this, but, if these sequences are done a lot, we can combine some of these sequences in helper functions to reduce some code replication (e.g. a function that combines the fgets followed by the sscanf)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Time {
char nome[100];
int gols_marcados;
int gols_sofridos;
} Time;
// RETURNS: 1=valid, 0=syntax error
int
entrada_dados(Time *timelist, int i)
{
char buf[100];
char *cp;
Time *tim = &timelist[i];
int valid = 0;
do {
// get name
if (fgets(tim->nome,sizeof(tim->nome),stdin) == NULL)
break;
// strip newline
tim->nome[strcspn(tim->nome,"\n")] = 0;
// get number using strtol
if (fgets(buf,sizeof(buf),stdin) == NULL)
break;
tim->gols_marcados = strtol(buf,&cp,10);
if (*cp != '\n')
break;
// get number using sscanf
if (fgets(buf,sizeof(buf),stdin) == NULL)
break;
if (sscanf(buf,"%d",&tim->gols_sofridos) != 1)
break;
// all input is okay
valid = 1;
} while (0);
return valid;
};
int
main(void)
{
int n = 0;
#if 0
scanf("%d", &n);
#else
char buf[100];
if (fgets(buf,sizeof(buf),stdin) == NULL)
exit(1);
sscanf(buf,"%d",&n);
#endif
// allocate sufficient space
Time *timelist = malloc(sizeof(*timelist) * n);
// read in data
int valid = 0;
for (int i = 0; i < n; i++) {
valid = entrada_dados(timelist, i);
if (! valid)
break;
}
// show the data
if (valid) {
for (int i = 0; i < n; i++) {
Time *tim = &timelist[i];
printf("nome='%s' gols_marcados=%d gols_sofridos=%d\n",
tim->nome,tim->gols_marcados,tim->gols_sofridos);
}
}
return 0;
}
Here is the program input:
3
Campinense
23
12
ABC
30
13
São Paulo
17
82
Here is the program output:
nome='Campinense' gols_marcados=23 gols_sofridos=12
nome='ABC' gols_marcados=30 gols_sofridos=13
nome='São Paulo' gols_marcados=17 gols_sofridos=82

How to input two strings separated by new line in C

How can I input 2 strings which are separated by a new line?
My Problem:
First I need to give how many strings I need to get and then I need to get those strings then display it.
I tried this:
Code:
#include <stdio.h>
#include <string.h>
int main()
{
int n,i = 0;
scanf("%d", &n);
char arr[n][100];
for(int i = 0; i < n; i++)
{
scanf("%[^\n]s", arr[i]);
}
for(int i = 0; i < n; i++)
{
printf("%s\n", arr[i]);
}
return 0;
}
My Input is :
2 I am
Aravind
My Output is:
I am
þ
First Line I got correct one but second line it shows some garbage value. Help me to solve this.
You have two major problems:
The "%[" format ends with the closing "]", there should be no "s" at the end.
The "%[" format doesn't skip leading space, like that newline which will be present after the first line you read.
Both these issues can be easily solve by using fgets to read whole lines instead.
You already have suggestions to not use scanf. However, if you 'must' use scanf then you can consider the following approach:
For dynamic memory allocation you should use malloc
the newline character stays in the stdin and hence needs to be flushed or handled/ignored
Here is the updated code.
int main()
{
int n,i = 0;
scanf("%d", &n);
scanf("%*[\n]");
/*this will read the \n in stdin and not store it anywhere. So the next call to
* scanf will not be interfered with */
char **inputs;
inputs = malloc(n * sizeof(char *));
for (i = 0; i < n; i++)
{
inputs[i] = malloc(100 * sizeof(char));
}
for(i = 0; i < n; i++)
{
scanf("%*[\n]");
scanf("%100[^\n]", inputs[i]);
}
for(i = 0; i < n; i++)
{
printf("%s\n", inputs[i]);
}
return 0;
}
use gets(arr[i]) instead of scanf.

Assignment makes pointer from integer without a cast and vice versa in c

I'm trying to write a program that gets a string, and a number, and calculates the length of it and shifting all the elents right.
I have 2 errors:
1.assignment makes pointer from integer without a cast.
2.assignment makes integer from pointer without a cast.
#include <stdio.h>
#include <string.h>
#define N 10
int myStrlen(char*);
void shiftRight(char*, int);
int main() {
char str[N] = {0};
int num = 0;
int len;
/* input of the string */
scanf("%s",str);
scanf("%d",&num);
len=myStrlen(str);
if(num>=0) {
shiftRight(str, num);
printf("%s\n",str);
}
else
{
printf("%s\n", str);
}
return 0;
}
int myStrlen(char*str)
{
int my_len=0;
while (str[my_len] != '\0')
{
my_len++;
}
return my_len;
}
void shiftRight(char* str, int num)
{
int i;
char* j;
int count;
j=(str[N-1]);
for(count=0;count<num;count++)
{
for(i=N-1;i>0;--i)
{
str[i]=str[i-1];
}
str[0]=j;
}
}
Your answers are welcome,anf if you anything wrong with this code,please mention it.
As your compiler will have told you, pointer from integer without a cast is at
j=(str[N-1]);
And integer from pointer is at
str[0]=j;
You should have declared j as char j;
But now when i run it, and typing lets say ball as a string and 1 to
be a number, i get nothing from the program instead of getting "lbal"
You have all the correct elements but that's not enough. Writing a program is telling a story, you need to set the scene, describe what happens along the way and conclude your narrative. A story with elements out of order is nonsense, as is a program.
Specific issues with your code: you're saving of the last character (to restore it to the beginning of the string) is in the wrong place; you're using the allocation of the string when you should be using it's length (and conveniently, you have a function for that!); this is really more of a rotation than a shift; use the most descriptive variable names you can, not the shortest you can get away with; pick one indentation style and stick with it -- it can change between programs you write but shouldn't change within an individual program.
Below is a rework of your code addressing some of the issues above:
#include <stdio.h>
#define STRING_SIZE 10
int myStrlen(char *string)
{
int length = 0;
while (string[length] != '\0')
{
length++;
}
return length;
}
void rotateRight(char *string, int number)
{
int length = myStrlen(string);
for (int count = 0; count < number; count++)
{
char j = string[length - 1];
for (int i = length - 1; i > 0; i--)
{
string[i] = string[i - 1];
}
string[0] = j;
}
}
int main()
{
char string[STRING_SIZE] = {0};
int number = 0;
/* input of the string */
scanf("%s", string);
scanf("%d", &number);
if (number > 0)
{
rotateRight(string, number);
printf("%s\n", string);
}
else
{
printf("%s\n", string);
}
return 0;
}
OUTPUT
% ./a.out
elephant
3
anteleph
%

Program that checks if an array is a palindrome

I'm trying to create a program that checks if a given array/string is a palindrome or not and its not working. The program just prints "0" on every given array, even on palindromes.
int main()
{
char string[100]= {0};
char stringReverse[100]= {0};
int temp = 0;
int firstLetter = 0;
int lastLetter = 0;
printf("Please enter a word or a sentence: ");
fgets(string, 100, stdin);
strcpy(stringReverse , string); // This function copies the scanned array to a new array called "stringReverse"
firstLetter = 0;
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
// This while reverses the array and insert it to a new array called "stringReverse"
while(firstLetter < lastLetter)
{
temp = stringReverse[firstLetter];
stringReverse[firstLetter] = stringReverse[lastLetter];
stringReverse[lastLetter] = temp;
firstLetter++;
lastLetter--;
}
printf("%s %s", stringReverse, string);
if ( strcmp(stringReverse , string) == 0)
{
printf("1");
}
else
{
printf("0");
}
}
Lets say we implement a simple fun to do that
int check_palindrome (const char *s) {
int i,j;
for (i=0,j=strlen(s)-1 ; i<j ; ++i, --j) {
if (s[i] != s[j]) return 0; // Not palindrome
}
return 1; //Palindrome
}
I think this is far more simpler ;)
For the code posted in question:
Be aware of fgets(). It stops in the first '\n' or EOF and keeps the '\n' character.
So if you give radar for ex, the result string will be "radar\n", which doesn't match with "\nradar"
The Problem:
Let's say you enter the string RACECAR as input for your program and press enter, this puts a newline character or a '\n' in your buffer stream and this is also read as part of your string by fgets, and so your program effectively ends up checking if RACECAR\n is a palindrome, which it is not.
The Solution:
After you initialize lastLetter to strlen(string) - 1 check if the last character in your string (or the character at the lastLetter index is the newline character (\n) and if so, decrease lastLetter by one so that your program checks if the rest of your string (RACECAR) is a palindrome.
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
// Add these 2 lines to your code
// Checks if the last character of the string read by fgets is newline
if (string[lastLetter] == '\n')
lastLetter--;
fgets adds a '\n' at the end.
So if the user entered "aba", string contains "aba\n".
reverseString contains "\naba".
So it doesn't match.
After the fgets, add this code
int l = strlen(string) - 1;
string[l] = 0;
This will strip out the '\n' at the end before copying it to reverseString.
That aside, you can do this whole program inplace without the need of a second buffer or strcpy or strlen calls.
You have several issues in your code:
first you forgot the last closing brace };
then you forgot to remove the trailing \n (or maybe also \r under Windows) in string;
you don't need to revert the string into a new string; a one-pass check is enough:
Here is a working code:
#include <stdio.h>
#include <string.h>
int main()
{
char string[100]= {0};
int temp = 0;
int firstLetter = 0;
int lastLetter = 0;
printf("Please enter a word or a sentence: ");
fgets(string, 100, stdin);
firstLetter = 0;
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
while ((string[lastLetter]=='\n')||(string[lastLetter]=='\r')) {
lastLetter--;
}
// This while reverses the array and insert it to a new array called "stringReverse"
temp = 1;
while(firstLetter < lastLetter)
{
if (string[firstLetter] != string[lastLetter]) {
temp = 0;
break;
}
firstLetter++;
lastLetter--;
}
if ( temp )
{
printf("1");
}
else
{
printf("0");
}
}
You can do it by this simpleway also.
#include <stdio.h>
#include <string.h>
int main()
{
char string[10], revString[10];
printf("Enter string for reversing it...\n");
scanf("%s", string);
int stringLength = strlen(string);
for(int i = 0; string[i] != '\0'; i++, stringLength--)
{
revString[i] = string[stringLength - 1];
}
if(strcmp(string, revString) == 0)
printf("Given string is pelindrom\n");
else
printf("Given string is not pelindrom\n");
}
#include<stdio.h>
#include<string.h>`enter code here`
void fun(char *a);
int main ()
{
char p[100];
char *s=p;
printf("enter the string");
scanf("%[^\n]",s);
fun(s);
}
void fun(char *a)
{
if(*a && *a!='\n')
{
fun(a+1);
putchar(*a);
}
}
// use this approach better time complexity and easier work hope this helps

Word length frequency in C Program

I am trying to write a simple C program to output the length of words and output their frequencies. For example, if the user inputs "hey" my program would output Length of word: 3 Occurrences 1, and so on with a larger string inputted. I just cannot seem to loop it properly. I thought of setting both counters when a delimiter is seen to count both the length of the word at the time and its occurrence but I have not found a way for it to work. How can I fix my loop? My code is below. I'd appreciate any help. I should include my program only runs correctly for one word inputted but not a whole sentence or multiple sentences.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
const char delim[] = ", . - !*()&^%$##<> ? []{}\\ / \"";
const int n_delim = 31;
#define SIZE 1000
int is_delim(int c);
int main(){
char string[SIZE];
int wordlength = 0, wl[SIZE];
int word = 0, i;
printf("Enter your input string:");
fgets(string, SIZE, stdin);
string[strlen(string) - 1] = '\0';
printf("Word Length\tCount\n");
int seen = 0;
int l;
for (i = 0; i < strlen(string); i++){
if (is_delim(string[i])){
wl[word++] = wordlength;
l = wordlength;
seen++;
printf("%d\t\t%d\n", l, seen);
wordlength = 0;
}
wordlength++;
}
return 0;
}
int is_delim(int c){
register int i;
for (i = 0; i < n_delim; i++)
if (c == delim[i]) return 1;
return 0;
}
The trick is that wl[n] holds the count of words
of length n. Also, you don't need to keep calling strlen()
on every iteration, just check for the zero byte at the end.
The optimizer will do this for you, if you enable it.
The odd-looking for(;1;) is so that the loop counts
the final word, which is terminated by the zero byte.
memset(wl,0,sizeof(wl));
for(wordStart=maxLength=i=0;1;i++) {
if(is_delim(string[i]) || string[i]==0) {
int wordLength= i-wordStart;
if(wordLength>0)
wl[wordLength]++;
if(wordLength>maxLength)
maxLength= wordLength;
wordStart= i+1;
}
if(string[i]==0)
break;
}
for(i=1;i<=maxLength;i++) {
if(wl[i]>0) {
printf("%d words of length %d.\n",wl[i],i);
}
}
You really should use strtok for this. Right now, you never compare the last string with the current one so you can't tell them apart. You can use strcmp for this. Finally instead of manually testing the length of the string you should use strlen. Here is how your loop could look like
int seen = 0;
pch = strtok(string, delim);
last = pch;
while(pch != NULL) {
if(strcmp(last, pch) != 0) {
printf("%s:\t%d\t\t%d\n", last, (int)strlen(last), seen);
seen = 1;
}else {
seen++;
}
last = pch;
pch = strtok(NULL, delim);
}
printf("%s:\t%d\t\t%d\n", last, (int)strlen(last), seen);
Note, you should set the variable seen to 0 before the loop.

Resources