Parsing a command line command without string library - c

So i am trying to parse a command from a command line like:
cd /mnt/cdrom
comes to
name = "cd"
argc = 2
argv = {"cd", "/mnt/cdrom", NULL}
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
void parse(char* line, command_t* command) {
// TODO: Check if string is empty or null
while (line[i] != ' ' && line[i] != '\0')
i++;
if (line[i] == ' ') {
}
// TODO: Split the string on whitespace -> should become an array of char
// TODO: The first string is the command, the length of tokens[1:] is the length of the arguments, and tokens[1:] are the arguments
// TODO: Create/fill-in the command struct with the data from above
}
That is as far as i have made it im not really sure how to split it at this point without string functions.

Well it's in haste solution, but it works.. Of course you need to dynamically allocate memory in parse function with some kind of list for example (for different arguments) and some kind of buffer for current argument processing.
#include <stdio.h>
#include <stdlib.h>
#define MAX_TOKEN 5
#define MAX_LENGTH 64
void copy_str( char* dst, char* src, int size ) {
int i = 0;
for( i = 0; i < size; ++i ) {
dst[i] = src[i];
}
}
char** parse( char* line, int size, int* argc ) {
int i = 0, j = 0;
char** argv = NULL;
argv = (char**)calloc( MAX_TOKEN, sizeof(char*) );
for( i = 0; i < MAX_TOKEN; ++i ) {
argv[i] = (char*)calloc( MAX_LENGTH, sizeof(char) );
}
for( i = 0; i < size; ++i ) {
if( line[i] == ' ' ) {
copy_str( argv[*argc], line + j, i - j );
j = i + 1; // length of token
(*argc)++;
}
}
// copy last
copy_str( argv[*argc], line + j, i - j );
(*argc)++;
return argv;
}
int main( ) {
int t = 0, i;
char* s = "cd /mnt/cdrom";
char** argv = parse( s, 13, &t );
for( i = 0; i < t; ++i ) {
printf( "%s\n", argv[i] );
}
t = 0;
s = "ls -l /home/";
argv = parse( s, 12, &t );
for( i = 0; i < t; ++i ) {
printf( "%s\n", argv[i] );
}
return 0;
}

Related

How to print a specific character from a string in C

I'm recently practicing looping. I learned how to print: for example home to h ho hom home. by using
#include <stdio.h>
#include <string.h>
int main (){
char s[100];
printf("Input string = ");
scanf("%[^\n]", s);
for (int i=1; i<=strlen(s); i++){
for(int j = 0; j<i; j++)
printf("%c", s[j]);
printf("\n");
}
return 0;
How can i reverse it so it can be
home
hom
ho
h
instead? thank you.
It is easy to do. For example
for ( size_t i = strlen( s ); i != 0; i-- )
{
for ( size_t j = 0; j < i; j++ )
{
putchar( s[j] );
}
putchar( '\n' );
}
Another way is the following
for ( size_t i = strlen( s ); i != 0; i-- )
{
printf( ".*s\n", ( int )i, s );
}
provided that an object of the type int is able to store the length of the passed string.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
int main( void )
{
const char *s = "home";
for (size_t i = strlen( s ); i != 0; i--)
{
printf( "%.*s\n", ( int )i, s );
}
}
The program output is
home
hom
ho
h
You could loop over the string using putc, but it might also be helpful to understand the destructive approach that shortens the string and uses %s to print strings. eg:
#include <stdio.h>
#include <string.h>
int
main(int argc, char **argv)
{
char *s = argc > 1 ? argv[1] : strdup("home");
for( char *e = s + strlen(s); e > s; e -= 1 ){
*e = '\0';
printf("%s\n", s);
}
return 0;
}
Note that this approach is destructive. When complete, the string is null. As an exercise, it might be helpful to fix that.
You'll basically go backwards in your loop.
Instead of:
for (int i=1; i<=strlen(s); i++){
You'd have
for (int i=strlen(s); i>0; i--){

How can I define and call this code as a function?

I'm new to programming.Im learning from CS50. I'm not sure on how to define this code as a function.I want the function to return key[n].And how to call the function?
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, string argv[])
{
int n = strlen(argv[1]);
int key[n];
int k =0;
for( int i = 0; i < strlen(argv[1]); i++)
{
if(islower(argv[1][i]) != 0)
{
for(int j = 97; j < argv[1][i]; j++)
{
k++;
}
key[i] = k;
k = k*0;
}
if(isupper(argv[1][i]) != 0)
{
for(int j = 65; j < argv[1][i]; j++)
{
k++;
}
key[i] = k;
k = k*0;
}
}
}
The function can look for example the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int * f( const char *s )
{
int *key = NULL;
size_t n = strlen( s );
if ( n != 0 && ( key = calloc( n, sizeof( int ) ) ) != NULL )
{
for ( size_t i = 0; i < n; i++ )
{
unsigned char c = s[i];
if ( islower( c ) ) key[i] = c - 'a';
if ( isupper( c ) ) key[i] = c - 'A';
}
}
return key;
}
int main( int argc, char * argv[] )
{
if ( argc == 2 )
{
int *key = f( argv[1] );
if (key != NULL)
{
// some other code
free( key );
}
}
return 0;
}
A function is a block of code with an "in" and "out". You define a function to receive values from the outside with syntax like int key (int example){} and pass in values to your function call with key(1);.
Your main() is also a function. The values that main() receives are being used in your code right now.
Your own function (which you define outside of main()) can be done in many ways, but the easiest would be to simply keep almost all of the same code within main() while figuring out how to transport what main() received into yours.

Delete space error in C programming

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#pragma warning(disable:4996)
#define SIZE 100
int main(void){
char str[SIZE];
char str2[SIZE];
int i;
int len;
gets(str);
len = strlen(str);
for (i = 0; str[i] != NULL; i++) {
if (str[i] != ' '){
str2[i] = str[i];
}
}
for (i = 0; i < len; i++){
printf("%c", str2[i]);
}
return 0;
}
It returns the following error:
What is the problem?
I just want to copy some elements in str to str2 without spaces, but when I run, it has got some weird letters.
You need two index variables
one to go through str
one to tell where to write next to str2
code:
len = strlen(str);
int j;
for (i=0, j=0 ; str[i] != '\0' ; i++) {
if (str[i] != ' '){
str2[j++] = str[i]; // store to str2 and increment j
}
}
Then store a final \0 to str2 at index j
str2[j] = '\0';
Finally, to print the result, you can do that one shot
printf("%s\n", str2);
instead of printing one char at a time.
For starters these headers
#include <stdlib.h>
#include <windows.h>
can be removed because neither declaration from the headers is used in the program.
The function gets is unsafe and is not supported by the C Standard any more. Instead use standard C function fgets.
When str is copied in str2 you have to use separate index to access characters in str2 because some characters from str are not copied. Otherwise the array str2 will contain gaps. As result you can not use the previous value of the variable len with the array str2.
Also it is desirable not to copy any other white space characters.
The program can look the following way
#include <stdio.h>
#include <ctype.h>
#define SIZE 100
int main(void)
{
char str[SIZE];
char str2[SIZE];
fgets( str, sizeof( str ), stdin );
const char *p = str;
char *p2 = str2;
do
{
if ( !isspace( ( unsigned char )*p ) )
{
*p2++ = *p;
}
} while ( *p++ );
for ( p2 = str2; *p2; ++p2 )
{
printf( "%c", *p2 );
}
return 0;
}
Its output might be
Hello World
HelloWorld
If you do not study yet pointers then the program can look like
#include <stdio.h>
#include <ctype.h>
#define SIZE 100
int main(void)
{
char str[SIZE];
char str2[SIZE];
fgets( str, sizeof( str ), stdin );
size_t i = 0, j = 0;
do
{
if ( !isspace( ( unsigned char )str[i] ) )
{
str2[j++] = str[i];
}
} while ( str[i++] );
for ( j = 0; str2[j]; ++j )
{
printf( "%c", str2[j] );
}
return 0;
}

Concatenate first characters from a command line argument in c

I have tried this solution, but don't know why it is giving segmentation fault.
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char st[1000]="";
for (int i=1; i<argc; i++)
{
strcat(st,argv[i][0]);
strcat(st,". ");
}
printf("%s", st);
return 0;
}
A solution without using any string-library functions at all might look like:
#include <stdio.h>
#define ARGV_MAX (5) /* Adjust this to match the maximum number of arguments
to be processed. */
#define RESULT_STR_MAX (3*ARGV_MAX +1) /* The chararacters per arg per maximum arguments
to be processed +1 for the 0-terminator. */
int main(int argc, char *argv[])
{
char st[RESULT_STR_MAX] = "";
size_t string_index = 0;
size_t argv_index = 1; /* Skip argv[0] below as it does not carry an
argument, but the program's name. */
while ((size_t) argc > argv_index
&& RESULT_STR_MAX > string_index /* in fact this or
&& ARGV_MAX >= argv_index) this would do. */
{
st[string_index] = argv[argv_index][0];
string_index++;
st[string_index] = '.';
string_index++;
st[string_index] = ' ';
string_index++;
argv_index++;
}
st[string_index] = '\0'; /* Add the '0'-terminator
to make the char array a "string".
(not necessary as st got initialised to all 0s).*/
if (ARGV_MAX < argv_index)
{
printf("Ignored the last %d argument(s).\n", argc - ARGV_MAX - 1);
}
puts(st);
return 0;
}
Below another approach using strcat():
#include <stdio.h>
#define ARGV_MAX (5) /* Adjust this to match the maximum number of arguments
to be processed. */
#define RESULT_STR_MAX (3*ARGV_MAX +1) /* The chararacters per arg per maximum arguments
to be processed +1 for the 0-terminator. */
int main(int argc, char *argv[])
{
char st[RESULT_STR_MAX] = "";
size_t argv_index = 1; /* Skip argv[0] below as it does not carry an
argument, but the program's name. */
while ((size_t) argc > argv_index
&& ARGV_MAX >= argv_index)
{
strcat(st, (char[2]){argv[argv_index][0]});
strcat(st, ". ");
argv_index++;
}
if (ARGV_MAX < argv_index)
{
printf("Ignored the last %d argument(s).\n", argc - ARGV_MAX - 1);
}
puts(st);
return 0;
}
Change this statement
strcat(st,argv[i][0]);
to
strncat(st, &argv[i][0], 1);
or
strncat(st, argv[i], 1);
In the original statement the function considers the character argv[i][0] as a pointer value. So the call has undefined behavior.
Or you can use a straightforward approach without using string functions. For example
#include <stdio.h>
int main( int argc, char * argv[] )
{
char st[1000];
size_t i = 0;
for ( int j = 1; j < argc; j++ )
{
st[i++] = *argv[j];
if ( j + 1 != argc )
{
st[i++] = ',';
st[i++] = ' ';
}
}
st[i] = '\0';
puts( st );
return 0;
}
try this:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char st[1000]="";
--argc, ++argv;//skip first.
char *p = st;
for (int i = 0; i < argc; i++){
if(i){//between ?
strcpy(p, ". ");
p += 2;
}
*p++ = argv[i][0];//copy one character
}
printf("%s\n", st);
return 0;
}

How to convert a string containing integers passed as command line arguements into an array of integers

./a.out "1 23 5 7 2 21"
I want to convert the above string passed as a command line argument into an array of integers in C programming. Would really appreciate help.
Thank you.
A simple loop can solve your problem-
int a[argc];
for(i = 0; i < argc; i++)
{
a[i] = atoi(argv[i+1]);
}
If passing a string
./a.out "1 23 5 7 2 21"
You need to tokenize the string whilst passing the "int" value to an array (which should be dynamic) since you are passing a string and not multiple options. (Which was what I initially thought, but changed)
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* For strtok */
int main( int argc, char **argv )
{
int i = 0;
int *intArray;
const char s[2] = " ";
char *token;
token = strtok(argv[1], s);
intArray = malloc(sizeof(int));
while( token != NULL )
{
intArray[i++] = atoi(token);
token = strtok(NULL, s);
}
//intArray holds the values but this is to display the results
int j;
for (j=0; j < i ; j++){
printf( " %d\n", intArray[j] );
}
return 0;
}
If passing multiple options (after program name)
./a.out 1 23 5 7 2 21
int i;
int intArray[argc-1];
for (i=0; i < argc - 1; i++){
intArray[i] = atoi(argv[i+1]);
}
return 0;
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char *argv[]){
if(argc != 2){
exit(EXIT_FAILURE);
}
int n = 0;//number of elements
char prev = ' ', *s = argv[1];
while(*s){
if(isspace(prev) && !isspace(*s))
++n;
prev = *s++;
}
int nums[n];
char *endp;
s = argv[1];
for(int i = 0; i < n; ++i){
nums[i] = strtol(s, &endp, 10);
s = endp;
printf("%d\n", nums[i]);//check print
}
return 0;
}

Resources