I can't figure out strcpy - c

This is an unfinished code for converting alphanumeric characters into Morse code. So far only the character "A" is in set. I can't seem to copy the Morse code string of "a" into the variable "c". The compiler tells me that passing argument 1 of strcpy makes pointer from integer without a cast.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(){
char c; /* variable to hold character input by user */
char sentence[ 80 ]; /* create char array */
int i = 0; /* initialize counter i */
const char *a = ".- ";
/* prompt user to enter line of text */
puts( "Enter a line of text:" );
/* use getchar to read each character */
while ( ( c = getchar() ) != '\n') {
c = toupper(c);
switch (c){
case 'A':
strcpy(c, a);
break
}
sentence[ i++ ] = c;
} /* end while */
sentence[ i ] = '\0'; /* terminate string */
/* use puts to display sentence */
puts( "\nThe line entered was:" );
puts( sentence );
return 0;
}

c is a single character, while a is a string (which explains both why c can only hold a single character, and why the compiler is complaining). If you want c to hold a whole string, declare it as such (like you did for sentence).

You've declared the variable c to have type char:
char c;
Then you're trying to use strcpy(c,a) -- but what type does strcpy expect for its first argument? Here's the signature from the manpage:
char *strcpy(char *dest, const char *src);

Related

how do I access a character from 2-D char string

#include <stdio.h>
#include <string.h>
#define max 50
#define len 30
char text[max][len];
void main(){
register int i;
printf("Enter an empty line to quit\n");
for(i =0 ;i<max;i++){
gets(text[i]);
if(!*text[i]){break;}
}
puts(text[1][0]);/*I want to display first character of second string but it doesn't print anything. Why??*/
}
how do i access character or part of string from array of string
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
The function gets is unsafe and is not supported by the C Standard. Instead use standard C function fgets.
The function puts expects an argument of the pointer type char * that points to a string. However you are passing an object of the type char
puts(text[1][0]);
that invokes undefined behavior.
Also declare variables in minimum scope where they are used. There is no great sense to declare the array text in the file scope.
The program can look the following way
#include <stdio.h>
#define MAX 50
#define LEN 30
int main( void )
{
char text[MAX][LEN] = { 0 };
puts( "Enter an empty line to quit" );
size_t i = 0;
while ( i < MAX && fgets( text[i], LEN, stdin ) != NULL && text[i][0] != '\n' )
{
++i;
}
if ( !( i < 2 ) ) printf( "%c\n", text[1][0] );
}
Pay attention to that the function fgets can store the new line character '\n' in the suppled array.
If you want to remove it then you can write for example
#include <string.h>
//...
text[i][ strcspn( text[i], "\n" ) ] = '\0';
In your code, puts(text[1][0]) is trying to print a text[1][0] which is a char, and puts only accepts an char*, leading to a segmentation fault on my computer.
But, printf allows you to print an char.
Fixed code:
#include <stdio.h>
#include <string.h>
#define max 50
#define len 30
char text[max][len];
void main(){
register int i;
printf("Enter an empty line to quit\n");
for(i =0 ;i<max;i++){
gets(text[i]);
if(!*text[i]){break;}
}
printf("%c\n", text[1][0]); /* printf allows you to print char */
}
Note: as said in the comments of the question, you can also use putchar() to print one character.
Input:
s
s
Output:
s

How to define "strchr(s,oldch)" in function definition in c program?

I am a beginner to C language. I dont understand the function defintion part. What does "strchr(s,oldch)" do?
I am trying to convert it into ctypes program.
#include <stdio.h>
#include <string.h>
#include <math.h>
/* Replace och with nch in s and return the number of replacements */
extern int replace(char *s, char och, char nch);
/* Replace a character in a string */
int replace(char *s, char oldch, char newch) {
int nrep = 0;
while (s = strchr(s,oldch)) {
*(s++) = newch;
nrep++;
}
return nrep;
}
/* Test the replace() function */
{
char s[] = "Skipping along unaware of the unspeakable peril.";
int nrep;
nrep = replace(s,' ','-');
printf("%d\n", nrep);
printf("%s\n",s);
}
what does while (s = strchr(s,oldch)) mean? what work it does ?
How to write it in other ways?
Can anyone explain it ?
The C library function char strchr(const char *str, int c) searches for the first occurrence of the character c (an unsigned char) in the string pointed to by the argument str.
strchr() function checks whether the original string contains defined characters. If the character is found inside the string, it returns a pointer value; otherwise, it returns a null pointer.
Syntax:
char *strchr(const char *str, int c)
Parameters
str − This is the C string to be scanned.
c − This is the character to be searched in str.
Example.
The following example shows the usage of strchr() function.
#include <stdio.h>
#include <string.h>
int main () {
const char str[] = "www.ted.com";
const char ch = '.';
char *ret;
ret = strchr(str, ch);
printf("String after |%c| is - |%s|\n", ch, ret);
return(0);
}
compile and run the above program that will produce the following result:
String after |.| is - |.ted.com|
The C library function strchr loops through an array of characters and returns the first occurrence of a certain character. In your case, you're looping through an array of characters(string) and replacing oldch with newch, then you're returning the total number of characters replaced in your string:-
/*
Declaring a function called replace that takes as input 3
arguments:-
> a string 's',
> character to be replaced in the string 'och'
> what to replace with 'nch'
*/
extern int replace(char *s, char och, char nch);
int replace(char *s, char oldch, char newch) {
//initialize our counter to keep track of characters replaced
int nrep = 0;
/*
call the function strchr and try to find if the next position of
the character we'd like to replace can be located, i.e. there's
still more old characters left in the string. If this is the
case, replace this character with 'newch' and continue doing this
until no more old characters can be found in the string, at which
point you return total number of old characters replaced (nrep).
*/
while (s = strchr(s,oldch)) {
//replace current oldch with newch and find next oldch
*(s++) = newch;
//increment number of characters replaced
nrep++;
}
return nrep;
}

Why I can't print first/last character right?

My output string needs to be palindrom of the input string. It works almost perfect but I am having problem with first character of the input string, my new string won't print it (in essence my new string won't print last character). Also strrev() does not work on Ubuntu so i need to do this without using that function.
#include <stdio.h>
#include <string.h>
int main(void){
int i,j=0;
char input_str[10];
char new_str[10];
printf("Enter characters:\n");
gets(input_str);
for(i=strlen(input_str)-1;i>0;i--){
new_str[j]=input_str[i];
j++;
}
printf("Output:\n");
printf("%s", new_str);
return 0;
}
For starters the function gets is unsafe function and is not supported by the C Standard.
You should use the standard C function fgets.
There are two problems with your code. The first one is in this loop
for(i=strlen(input_str)-1;i>0;i--){
new_str[j]=input_str[i];
j++;
}
the index i equal to 0 is skipped from using it to copy the corresponding character of the source string.
The second one is the destination array is not appended with the terminating zero character.
Here is a demonstrative program that shows how a function that makes a reversed copy of a source string can be implemented.
#include <stdio.h>
#include <string.h>
char * reverse_copy( char *dsn, const char *src )
{
size_t n = strlen( src );
size_t i = 0;
for ( ; i < n; i++ )
{
dsn[i] = src[n - i - 1];
}
dsn[i] = '\0';
return dsn;
}
int main(void)
{
enum { N = 10 };
char input_str[N] = "";
char new_str[N];
printf( "Enter a string (less than %zu symbols): ", ( size_t )N );
fgets( input_str, N, stdin );
input_str[ strcspn( input_str, "\n" ) ] = '\0';
printf( "\"%s\"\n", input_str );
printf( "\"%s\"\n", reverse_copy( new_str, input_str ) );
return 0;
}
The program output might look for example the following way
Enter a string (less than 10 symbols): Hello
"Hello"
"olleH"
i is never zero. That is why the first character (input_str[0]) is ignored.

My Loop Won't Check All Elements Of Array in C

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void displayString (const char *sPtr);
void getString (char *[]);
int determinIfConvert (char);
int main ()
{
char originalString[11] = { 0 };
char convertedString[11];
getString (originalString);
displayString (originalString);
// this loop runs through the "originalString" to check for the char: 'a'
for (int i = 0; i < 11; i++) {
determinIfConvert (originalString[i]);
}
system ("pause");
}
void getString (char *a[]) // this function gets a string
{
printf ("enter 11 char string: \n");
scanf ("%s", a);
}
// this program displays the inputstring
void displayString (const char *sPtr)
{
for (; (*sPtr != '\0'); ++sPtr) {
printf ("%c", *sPtr);
}
}
int determinIfConvert (char *a)
{
if (a == 97) // this is a test condition. The goal is to
// check for all lowercase, but now i'm
// only entering "aaaaa"
{
printf ("Works"); // if it prints multiple"works"
// then i can continue my program
// but it only prints ONE "works" and freezes.
}
}
At the moment I have a problem with my For Loop in main() not finishing. The goal is to enter a string of characters, and then check for lowercase ones. This will be done with the function DeterminIfConvert(char). However, when I run through the loop element by element, it freezes after the second element. My test data is "aaaa" and it prints the "aaaa," so I know that my first two functions work just fine. I get to the loop, it goes through the first element, prints "works" and then freezes. :/
Multiple mistakes
void getString(char *a[])
should be
void getString(char a[])
Since you're sending the base address of an array of char, not an array of pointer to char
char *a[]; // array of pointer to char
char a[]; // array of char
int determinIfConvert(char *a)
should be
int determinIfConvert(char a)
Since you're sending a char, not a pointer to char
char * a; // pointer to char
char a; // char
NOTE:
Use the standard definition of main()
int main(void) //if no command line arguments.
If you are inputting an 11-char string, then you should be doing:
char originalString[12] = { 0 };
This is because you need 1 more character to store the null character '\0'.
That is probably why in your function getString(...), the pointer exceeds the array bounds and might invoke undefined behavior.
Finally, your function prototype for getString(...) should be
void getString(char a[]); //without the *
In addition to the other answers, you have several other areas where you can improve your code.
Avoid using magic numbers in your code (e.g. 11). Instead define a constant for the maximum characters in your string #define MAXC 11 or you can use an enum instead enum { MAXC = 11 };
As it currently sits, you do not protect against overflowing your 11 character array (which means your user can enter no more than 10 characters plus room for the nul-terminating character). To protect against the user entering something more than 10, you should use a field-width specifier with scanf:
scanf ("%10s", a);
That doesn't solve your problems with scanf. You must check the return every time to insure the expected number of conversions takes place, e.g.:
if (scanf ("%10s", a) != 1) {
fprintf (stderr, " -> error: invalid input.\n");
exit (EXIT_FAILURE);
}
That's better, but using %s, you cannot read a string containing whitespace, and you are still leaving a trailing '\n' in the input buffer. If the users enters "my dog", you store "my" only. To fix part of the problem you can use a format specifier of "%10[^\n]%*c". However, you must protect against an endless-loop if the user presses [Enter] without other input. To resolve all issues, and prevent leaving the trailing newline in the input buffer, you can use something like:
int getString (char *a) // this function gets a string
{
int c, rtn = 0;
printf ("enter string (10 char or less): ");
while ((rtn = scanf ("%10[^\n]%*c", a)) != 1) {
if (rtn == EOF)
break;
fprintf (stderr, " -> error: invalid input, try again..\n");
printf ("enter string (10 char or less): ");
/* flush input buffer - to avoid endless loop */
while ((c = getchar()) != '\n' && c != EOF) {}
}
return rtn;
}
All of which expose the difficulties using scanf for user input. A better approach may be to use fgets (or getline) to read the complete line of input.
Regardless whether you use scanf or fgets, etc.. you must take a bit of time and care in writing your input handlers to insure you try and cover all ways a user could muck up input. Below fgets is used just to present an alternative. You should also choose a return type that allows you to tell whether you have successfully received input or not. It might as well be a useful return such as the length of the input taken, etc..
The remainder of your level of pointer indirection issues have been addressed by other answers. Putting it all together, you could do something like:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 11
void displayString (const char *sPtr);
int getString (char *);
int determinIfConvert (char);
int main (void)
{
char originalString [MAXC] = "";
// char convertedString[MAXC] = ""; /* currently unused */
if (!getString (originalString)) {
fprintf (stderr, "error: getString failed.\n");
return 1;
}
displayString (originalString);
// this loop runs through the "originalString" to check for the char: 'a'
for (int i = 0; i < 11; i++) {
determinIfConvert (originalString[i]);
}
system ("pause");
return 0; /* main() is type 'int' and returns a value */
}
int getString (char *a) // this function gets a string
{
char *p = a;
int c;
size_t len = 0;
printf ("enter string (10 char or less): ");
for (;;) {
p = fgets (a, MAXC, stdin);
if (!p) break; /* handle [CTRL+D] */
if (*p == '\n') { /* handle empty str */
fprintf (stderr, " -> error: invalid input, try again..\n");
printf ("enter string (10 char or less): ");
continue;
}
/* trim newline/flush input buffer */
len = strlen (p);
if (len && a[len - 1] == '\n')
a[--len] = 0;
else /* user entered more than 10 chars */
while ((c = getchar()) != '\n' && c != EOF) {}
break;
}
return (int) len;
}
// this program displays the inputstring
void displayString (const char *sPtr)
{
for (; *sPtr; sPtr++) {
printf ("%c", *sPtr);
}
putchar ('\n');
}
int determinIfConvert (char a)
{
if (a == 97)
printf ("Works\n");
return 0;
}
Example Use/Output
$ ./bin/getdispstr
enter string (10 char or less): my dog has fleas
my dog has
Works
$ ./bin/getdispstr
enter string (10 char or less):
-> error: invalid input, try again..
enter string (10 char or less): my dog has fleas, my cat has none.
my dog has
Works
With CTRL+D (EOF)
$ ./bin/getdispstr
enter string (10 char or less): error: getString failed.
There are many ways to do this, this is just an example. Look over all the answers and let me know if you have questions.
This
char originalString[11] = { 0 };
followed by this
for (int i = 0; i < 11; i++)
{
determinIfConvert(originalString[i]);
}
is causing the problem. You see the array of char does not have elements post index 0. And yeah I believe what you are trying to attempt with
getString(originalString); seems like you want to get originalString from user input which is not correctly executed in your case.
You pass object of type char to a function accepting char*
char originalString[11] = { 0 };
determinIfConvert(originalString[i]);
int determinIfConvert(char *a)
A string is nothing but a null terminated set of characters, so if you wish to have 11 characters in you string, you should be allocating 12 bytes to your
array, ie you may change :
char originalString[11] = { 0 };
to
char originalString[12] = "";
/* Here is the string is empty but because you use double quotes
* compiler understands that you are initializing a string, so '\0' is auto
* appended to the end of it by the compiler to mark the end of the string.
*/
So is the case with convertedString[11] change it to
char convertedString[12] = "";
Change
void getString(char *a[]);
to
void getString(char a[]); //char *a is also fine
Change
int determinIfConvert(char *a)
to
int determinIfConvert(char a) // You wish to check a character
You may wish to replace
scanf("%s", a);
with
fgets(a,12,stdin);
because scanf can't check for overflows but fgets can. Here you can have up to 11 characters in the string. If an overflow occurs, the rest of the input is trimmed and '\0' is assigned to the 12th byte.
You may wish to use the islower function to check is a character is lowercase. So you may change
if (a == 97)
to
if (islower(a)) // check if a character is lowercase.
Remember you may need to include the string.h header to use islower()

Building a basic shell, more specifically using execvp()

In my program I am taking user input and parsing it into a 2d char array. The array is declared as:
char parsedText[10][255] = {{""},{""},{""},{""},{""},
{""},{""},{""},{""},{""}};
and I am using fgets to grab the user input and parsing it with sscanf. This all works as I think it should.
After this I want to pass parsedText into execvp, parsedText[0] should contain the path and if any arguments are supplied then they should be in parsedText[1] thru parsedText[10].
What is wrong with execvp(parsedText[0], parsedText[1])?
One thing probably worth mentioning is that if I only supply a command such as "ls" without any arguments it appears to work just fine.
Here is my code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "308shell.h"
int main( int argc, char *argv[] )
{
char prompt[40] = "308sh";
char text[40] = "";
char parsedText[10][40] = {{""},{""},{""},{""},{""},
{""},{""},{""},{""},{""}};
// Check for arguments to change the prompt.
if(argc >= 3){
if(!(strcmp(argv[1], "-p"))){
strcpy(prompt, argv[2]);
}
}
strcat(prompt, "> ");
while(1){
// Display the prompt.
fputs(prompt, stdout);
fflush(stdout);
// Grab user input and parse it into parsedText.
mygetline(text, sizeof text);
parseInput(text, parsedText);
// Check if the user wants to exit.
if(!(strcmp(parsedText[0], "exit"))){
break;
}
execvp(parsedText[0], parsedText[1]);
printf("%s\n%s\n", parsedText[0], parsedText[1]);
}
return 0;
}
char *mygetline(char *line, int size)
{
if ( fgets(line, size, stdin) )
{
char *newline = strchr(line, '\n'); /* check for trailing '\n' */
if ( newline )
{
*newline = '\0'; /* overwrite the '\n' with a terminating null */
}
}
return line;
}
char *parseInput(char *text, char parsedText[][40]){
char *ptr = text;
char field [ 40 ];
int n;
int count = 0;
while (*ptr != '\0') {
int items_read = sscanf(ptr, "%s%n", field, &n);
strcpy(parsedText[count++], field);
field[0]='\0';
if (items_read == 1)
ptr += n; /* advance the pointer by the number of characters read */
if ( *ptr != ' ' ) {
strcpy(parsedText[count], field);
break; /* didn't find an expected delimiter, done? */
}
++ptr; /* skip the delimiter */
}
}
execvp takes a pointer to a pointer (char **), not a pointer to an array. It's supposed to be a pointer to the first element of an array of char * pointers, terminated by a null pointer.
Edit: Here's one (not very good) way to make an array of pointers suitable for execvp:
char argbuf[10][256] = {{0}};
char *args[10] = { argbuf[0], argbuf[1], argbuf[2], /* ... */ };
Of course in the real world your arguments probably come from a command line string the user entered, and they probably have at least one character (e.g. a space) between them, so a much better approach would be to either modify the original string in-place, or make a duplicate of it and then modify the duplicate, adding null terminators after each argument and setting up args[i] to point to the right offset into the string.
You could instead do a lot of dynamic allocation (malloc) every step of the way, but then you have to write code to handle every possible point of failure. :-)

Resources