Sprintf with pointers, constants and string formatting - c

I am new to C and I have had trouble simplifying this program. I am trying to initalize name once and strcat name to command once. It is a command line executable that takes two args and one optional arg for the filename "new py" or "new txt", or "new py script". I run Windows's MinGW to compile.
Is there a type to allow storage of argv value and a string constant with one line?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char command[100] = "cd . > ";
char *type = argv[1];
char * name;
strcat(command,"\"");
if (argc == 3) {
char * name = argv[2];
//strcat(command,name);
} else {
char name[20];
sprintf(name,"new %s file",type);
//strcat(command,str);
}
strcat(command,name);
strcat(command,".");
strcat(command,type);
strcat(command,"\"");
system(command);
return 0;
}

As mentioned by BLUEPIXY, my block needs to include "char name[20]; if(argc == 3){ strcpy(name, argv[2]); } else { sprintf(name,"new %s file",type); } strcat(command, name);". After those changes, I converted all of the strcats to one sprinf.
My previous understanding of storing argv items was that char pointers were needed for compilation because args wouldn't be defined. They are not needed any more because of the initialization of name.
My now condensed code is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char command[100];
char * type = argv[1];
char name[50];
if (argc == 3) {
strcpy(name, argv[2]);
} else {
sprintf(name,"new %s file",type);
}
sprintf(command,"cd . > \"%s.%s\"",name,type);
system(command);
return 0;
}
Again, thank you BLUEPIXY for clearing my misunderstanding.

Related

How do I prevent string overflow in C?

I'm trying to make a program which concatenates two strings. The max length of the strings should be 50 characters and I'm making a string with that size. I'm getting the strings using argv. How can I detect if the strings are over 50 characters? Can I do it without playing around with memory since I haven't learned this yet. The function for concatenation is stored in a mystrings.h file Here's my current code:
#include <stdio.h>
#include <string.h>
#include "mystrings.h"
int main(int argc, char *argv[]) {
if (argc == 3) {
char str1[50];
char str2[50];
strcpy(str1, argv[1]);
strcpy(str2, argv[2]);
strConcat(str1, str2);
printf("Concatenated string: %s\n", str1);
} else {
printf("Invalid number of arguments passed. Format required:\n <STRING1> <STRING2>\n");
}
}
Take the addition of their strings lengths and ensure it is less than the size of your buffer.
It must be less than the size of the buffer because you must leave room for the null-terminating byte.
No dynamic memory allocation needed.
#include <stdio.h>
#include <string.h>
#define LIMIT 50
int main(int argc, char **argv)
{
if (argc < 3) {
fprintf(stderr, "usage: %s STRING1 STRING2\n", argv[0]);
return 1;
}
if (strlen(argv[1]) + strlen(argv[2]) >= LIMIT) {
fprintf(stderr, "Combined string length is too long.\n");
return 1;
}
char result[LIMIT];
strcpy(result, argv[1]);
strcat(result, argv[2]);
puts(result);
}
As said by Shawn use the strlen() function have a look at the cs50 documentation I find it quite beginner friendly. A possible version of your code could be this:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc == 3)
{
char str1[50];
char str2[50];
if (strlen(argv[1]) > 50 || strlen(argv[2]) > 50)
{
printf("Max string length is 50");
return 1;
}
strcpy(str1, argv[1]);
strcpy(str2, argv[2]);
strConcat(str1, str2);
printf("Concatenated string: %s\n", str1);
}
else
{
printf("Invalid number of arguments passed. Format required:\n <STRING1> "
"<STRING2>\n");
}
}
About the concat strings. All it is doing is allocating memory with malloc and then copying the strings to the newly allocated memory while doing some checks to avoid unwanted behavior. It can be a bit confusing in the beginning, but it gets easier.

strcpy is not working well with pointer array

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *ptr;
char temp[20];
if (strlen(argv[1]) < strlen(argv[2]))
{
strcpy(temp,argv[1]);
strcpy(argv[1],argv[2]);
strcpy(argv[2],temp);
}
ptr = strstr(argv[1],argv[2]);
if (ptr == NULL)
printf("Non-inclusive");
else
printf("%s is part of %s", argv[2], argv[1]);
return 0;
}
When I enter "abc abcd",
I want to get "abc is part of abcd" as a result,
but real result is "abc is part of abcdabc"
The length of each string in the argv array is fixed. So when you attempt to swap the contents of argv[1] and argv[2] when their sizes are different you write past the end of the shorter one. This triggers undefined behavior.
Better to use separate char * variables, one pointing the longer string and one pointer to the shorter.
int main(int argc, char *argv[])
{
char *ptr;
char *s_short, *s_long;
if (strlen(argv[1]) < strlen(argv[2])) {
s_short = argv[1];
s_long = argv[2];
} else {
s_short = argv[2];
s_long = argv[1];
}
ptr = strstr(s_long,s_short);
if (ptr == NULL)
printf("Non-inclusive");
else
printf("%s is part of %s", s_short, s_long);
return 0;
}

Segmentation fault in C (beginner)

I'm a newbie in C programming and having pretty simple code here.
It compiles but won't run and a segmentation fault appears. I was looking for hours what could be wrong. Now I have a pretty good idea what segmentation fault means but not why it shows up in my small piece of code:
It's supposed to print out the user_id and group_id of the given parameter.
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
int main(int argc, char *argv[]){
if(argc != 1){
printf("ERROR");
}
struct passwd str;
struct passwd *pointer = getpwnam(argv[1]);
str = *pointer;
printf("user: %d /ngroup: %d",str.pw_uid, str.pw_gid);
return 0;
}
You should check pointer != NULL before assign it into str.
getpwnam() return NULL in case no entry was found or an error occurred. See https://linux.die.net/man/3/getpwnam for more detail.
I can detect some problems here:
Check if number of arguments is greater than 0, otherwise exit your program
You should check if return value from getpwnamreturns NON-NULL value.
I would rewrite this to:
int main(int argc, char *argv[]){
struct passwd str;
struct passwd *pointer;
//Number of arguments check
if (argc <= 1) {
printf("ERROR");
exit(0);
}
pointer = getpwnam(argv[1]);
if (pointer) {
str = *pointer;
printf("user: %d /ngroup: %d\r\n",str.pw_uid, str.pw_gid);
printf("user: %d /ngroup: %d\r\n", pointer->pw_uid, pointer->pw_gid);
}
return 0;
}
You probably want this:
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <pwd.h>
int main(int argc, char *argv[]){
if(argc < 2){
printf("usage: %s username", argv[0]);
return 1;
}
struct passwd *pointer = getpwnam(argv[1]);
if (pointer == NULL) {
printf("user: %s does not exist\n", argv[1]);
return 1;
}
printf("uid: %d\ngroup: %d\n", pointer->pw_uid, pointer->pw_gid);
return 0;
}
You need to check if getpwnam returns NULL. If yes, that means that the user does not exist and dereferencing a NULL pointer results in undefined behaviour (usually a seg fault).
BTW: the variable struct passwd str is not needed, you can access pointer directly.

Print the environment variables WITHOUT VALUES in C

How to print the environment variables in C, but WITHOUT VALUES ?? Only variables.
int main(int argc, char **argv, char **envp)
{
while(*envp!=NULL) {
printf("%s\n", *envp);
envp++;
}
system("pause");
return 0;
}
Since environmental variables have format of NAME=value you need to display only part of string up to = character.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
while(*envp!=NULL) {
char * len = strchr(*envp, '=');
if (len == NULL)
printf("%s\n", *envp);
else
printf("%.*s\n", len - *envp, *envp);
envp++;
}
system("pause");
return 0;
}
Ideone
Environment variables are of the form NAME=value. So, you can look for the first = sign and print only upto it to get only the names.

Iterate through char array and print chars

I am trying to print each char in a variable.
I can print the ANSI char number by changing to this printf("Value: %d\n", d[i]); but am failing to actually print the string character itself.
What I am doing wrong here?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int len = strlen(argv[1]);
char *d = malloc (strlen(argv[1])+1);
strcpy(d,argv[1]);
int i;
for(i=0;i<len;i++){
printf("Value: %s\n", (char)d[i]);
}
return 0;
}
You should use %c format to print characters in C. You are using %s, which requires to use pointer to the string, but in your case you are providing integer instead of pointer.
The below will work. You pass in the pointer to a string when using the token %s in printf.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int len = strlen(argv[1]);
char *d = malloc (strlen(argv[1])+1);
strcpy(d,argv[1]);
printf("Value: %s\n", d);
return 0;
}

Resources