I've been learning C for like 5 days, and so I tried doing some little projects.
I created a very simple library that automates getting a string from the user,then implemented it in a program which just outputs the string's value.
It runs perfectly on Windows (Compiled through MSVC: 'cl .\main.c /link .\get_string\m_string.obj') but it doesn't in Linux (Compiled with gcc using : 'gcc -o test main.c m_string.o')
I know that MAX being 1024 makes absolutely no sense, it's just a test value.
//main.c
#include <stdio.h>
#include "get_string/m_string.h"
int main(int argc, char *argv[])
{
char *inputf = get_string("Something: ");
printf("%s", inputf);
return 0;
}
// m_string.h
#include <stdio.h>
#define MAX 1024
char *get_string(char *prompt);
//m_string.c
#include "m_string.h"
char *get_string(char *prompt)
{
char *s[MAX];
printf("%s", prompt);
fgets(s, MAX, stdin);
return s;
}
Running main.c on Windows works as expected:
Something: something
something
Running main.c on Linux:
Something: something
(null)$
Since I am using a very big value for the maximum memory used in fgets(), I don't think that a buffer overflow is the cause (Would have probably gotten Segmentation Fault otherwise).
Thank you for reading and I hope someone can shed some light on the matter for an absolute beginer like me.
char *s[MAX]; creates an array of MAX pointers, not char values.
ALWAYS enable your compiler's warnings. It would have found this. With gcc, I use -Wall -Wextra -pedantic.
get_string returns a pointer to a variable that no longer exists once get_string returns.
One way to solve this is to allocate a buffer using malloc, and free that buffer in the caller.
#include <stdio.h>
#include <stdlib.h>
#define MAX 1024
char *get_string( const char *prompt ) {
char *s = malloc( MAX );
if ( !s )
return NULL;
printf( "%s", prompt );
if ( !fgets( s, MAX, stdin ) ) {
free( s );
return NULL;
}
return s;
}
int main( void ) {
char *inputf = get_string( "Something: " );
if ( !inputf ) {
perror( NULL );
exit( 1 );
}
printf( "%s", inputf );
free( inputf );
return 0;
}
Demo on Compiler Explorer
It really does not run "correctly", because this is undefined behavior. You may not access temporary storage outside of the scope in which it was defined.
In addition to this, you also have a type error: char *s[MAX]; defines an array of MAX char pointers. Using this as a string buffer should not have been allowed past the compiler.
If you do not want to allocate memory dynamically for this, then make the string buffer static. You can even make it thread-local (since C11) if for some reason you plan to use this function in concurrent environments.
#include <stdio.h>
#define MAX 1024
char *get_string(const char *prompt)
{
static _Thread_local char s[MAX];
printf("%s", prompt);
if (!fgets(s, MAX, stdin)) {
s[0] = '\0';
}
return s;
}
int main(int argc, char *argv[])
{
char *inputf = get_string("Something: ");
printf("%s", inputf);
return 0;
}
Related
I need to know a way for use environment variables in the C programming language. How can I use and read them?
For example, read an environment variable or take the value of an environment variable and load it in another variable.
You can use following functions -
char * getenv (const char *name)-returns a string that is the value of the environment variable name.
char * secure_getenv (const char *name)
Read about some more functions here -http://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access
Use the getenv function from stdlib.h. That's it!
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("test\n");
const char* s = getenv("PATH");
// If the environment variable doesn't exist, it returns NULL
printf("PATH :%s\n", (s != NULL) ? s : "getenv returned NULL");
printf("end test\n");
}
getenv:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char* my_env_var = getenv("MY_ENV_VAR");
if(my_env_var)
printf("Var found: %s", my_env_var );
else
printf("Var not found.");
return 0;
}
On windows, you would use GetEnvironmentVariable.
#include <stdio.h>
#include <winbase.h>
int main(int argc, char *argv[])
{
TCHAR buff[100] = T("");
DWORD resultLengthInCharacters = GetEnvironmentVariable(T("USERDOMAIN"), buff, 100);
if (resultLengthInCharacters > 0 && resultLengthInCharacters < 100) {
_tprintf(T("USERDOMAIN: %s\n"), buff);
} else if ( resultLengthInCharacters > 100) {
_tprintf(T("USERDOMAIN too long to store in buffer of length 100, try again with buffer length %lu\n"), resultLengthInCharacters);
} else {
// Error handling incomplete, should use GetLastError(),
// but typically:
_tprintf(T("USERDOMAIN is empty or not set in the Environment\n"));
}
return 0;
}
But if you are trying to get a standard path variable, you should use the SHGetFolderPath function with the right CSIDL variable (like from this question: How do I get the application data path in Windows using C++?)
Another way could be to use the global variable environ.
#include <stdio.h>
extern char** environ;
void main(int argc, char* argv[])
{
int i=0;
while(environ[i]!=NULL){
printf("%s\n",environ[i++]);
}
}
I have a piece of code when I need to include stdlib.h. When I do not include this header, I have no problems compiling my code, but the moment I include the header, my code refuses to compile. It tells me that it expected an identifier or "(" before numerical constant. I have looked through my code and cannot find any issue, and as stated, the code compiles perfectly without including that header.
I am new to C, so excuse my poor code, I am simply wanting to figure out why it would be giving me this error.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int execute(char **args)
{
}
char** parse(void)
{
char command[256];
fgets(command, sizeof(command), stdin);
char delimiter[] = " ";
char * pointer = strtok(command, delimiter);
int tokens = 0;
char ** final_command;
while (pointer != NULL)
{
// final_command = (char**)realloc(final_command,
// (tokens+1)*sizeof(char*));
//printf("%s\n", pointer);
//pointer = strtok(NULL, delimiter);
}
}
int main(int argc, char **argv)
{
int EXIT_SUCCESS = 1;
do
{
printf("MyShell> ");
char ** command = parse();
} while (EXIT_SUCCESS);
return EXIT_SUCCESS;
}
I compile using the command gcc -o MyShell MyShell.c
The exact error I am getting says "error: expected identifier or '(' before numeric constant int EXIT_SUCCESS = 1;"
EXIT_SUCCESS is a standard macro (definition) in C. Do not use it as a variable name.
Like NULL, EXIT_SUCCESS is a macro defined in <stdlib.h>, if you include <stdlib.h> you must not use this identifier for other purposes.
In any case your code does not make much sense because it looks like you've got an infinite loop there in main.
Its a simple input that I want to make for char*. Why is this not working?
It throws me an exception that I can't resolve..
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
char* GetCharSeq()
{
char *s = (char*)malloc(100);
scanf_s("%s", s);
return s;
}
int main()
{
char* charseq;
charseq = GetCharSeq();
return 0;
}
You have undefined behavior in your code. You have it because you provide to few arguments to the scanf_s function.
For every string argument, you need to provide not only the destination string but also the size of the string. So change your call to
scanf_s("%s", s, 100);
modify your code
char* GetCharSeq()
{
char *s = (char*)malloc(100);
gets(s);
return s;
}
This will work.
I have the following code:
#include <stdio.h>
#include <stdlib.h>
FILE * f_enter;
void CleanLineFeed(char * pCad)
{
char *cTmp;
char *ptr;
cTmp=pCad;
ptr = strtok(cTmp, "\r\n\r");
strcpy(pCad, ptr);
}
int main(int argc, char *argv[])
{
char datenter[127];
int i;
f_enter=fopen("data.txt","r");
if(f_enter == NULL)
{
printf("No data.txt.\n");
return 1;
}
while ( fgets(datenter, 127, f_enter) )
{
CleanLineFeed(datenter);
for(i=0; i < strlen(datenter);i++)
{
printf("%c-%0X\n",datenter[i], datenter[i]);
}
printf("----------------------\n");
}
return 0;
}
when i run it on Windows there is no error but
when i run it on Linux give me a segmentation fault error
Please, i strongly appreciate some kind of help
you forgot to
#include <string.h>
Man page on Ubuntu 14.04 for strcpy says "The strings may not overlap".
"CleanLineFeed" performs an overlapped strcpy().
( This Link describes the issue )
Windows implementation of "strcpy" may differ from Linux's implementation,
which may explain why one crashes and the other doesn't.
I need to know a way for use environment variables in the C programming language. How can I use and read them?
For example, read an environment variable or take the value of an environment variable and load it in another variable.
You can use following functions -
char * getenv (const char *name)-returns a string that is the value of the environment variable name.
char * secure_getenv (const char *name)
Read about some more functions here -http://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access
Use the getenv function from stdlib.h. That's it!
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("test\n");
const char* s = getenv("PATH");
// If the environment variable doesn't exist, it returns NULL
printf("PATH :%s\n", (s != NULL) ? s : "getenv returned NULL");
printf("end test\n");
}
getenv:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char* my_env_var = getenv("MY_ENV_VAR");
if(my_env_var)
printf("Var found: %s", my_env_var );
else
printf("Var not found.");
return 0;
}
On windows, you would use GetEnvironmentVariable.
#include <stdio.h>
#include <winbase.h>
int main(int argc, char *argv[])
{
TCHAR buff[100] = T("");
DWORD resultLengthInCharacters = GetEnvironmentVariable(T("USERDOMAIN"), buff, 100);
if (resultLengthInCharacters > 0 && resultLengthInCharacters < 100) {
_tprintf(T("USERDOMAIN: %s\n"), buff);
} else if ( resultLengthInCharacters > 100) {
_tprintf(T("USERDOMAIN too long to store in buffer of length 100, try again with buffer length %lu\n"), resultLengthInCharacters);
} else {
// Error handling incomplete, should use GetLastError(),
// but typically:
_tprintf(T("USERDOMAIN is empty or not set in the Environment\n"));
}
return 0;
}
But if you are trying to get a standard path variable, you should use the SHGetFolderPath function with the right CSIDL variable (like from this question: How do I get the application data path in Windows using C++?)
Another way could be to use the global variable environ.
#include <stdio.h>
extern char** environ;
void main(int argc, char* argv[])
{
int i=0;
while(environ[i]!=NULL){
printf("%s\n",environ[i++]);
}
}