I've been trying to use strtok in order to write a polynomial differentiation program, but it seems to be behaving oddly. At this point I've told it to stop at the characters ' ', [, ], (, and ). But for some reason, when passed input such as "Hello[]" it returns "Hello\n"
Is there anything wrong with my code here? All the polynomial string is is the text "Hello[]"
void differentiate(char* polynomial)
{
char current[10];
char output[100];
strncpy(current, strtok(polynomial, " []()/\n"), 10);
printf("%s", current);
} // differentiate()
EDIT : It appears to be an issue related to the shell, and it would also appear to not be a newline after all, as when I use bash it does not occur, but when I use fish, I get the following:
I've never seen this kind of thing before, does anyone have any advice? Is this just a quirk of fish?
I converted your code into this SSCCE (Short, Self-Contained, Correct Example):
#include <string.h>
#include <stdio.h>
static
void differentiate(char* polynomial)
{
char current[10];
strncpy(current, strtok(polynomial, " []()/\n"), 10);
printf("<<%s>>\n", current);
}
int main(void)
{
char string[] = "Hello[]";
printf("Before: <<%s>>\n", string);
differentiate(string);
printf("After: <<%s>>\n", string);
return 0;
}
Actual output:
Before: <<Hello[]>>
<<Hello>>
After: <<Hello>>
I was testing with GCC 4.8.1 on Mac OS X 10.8.4, but I got the same result with the Apple-supplied GCC (i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)) and clang (Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)).
You should justify your assertion that you got a newline out of strtok() by adapting this test and showing the output. Note how the code uses the << and >> to surround the string it is printing; if there's a newline in there, it will show up inside the double angle brackets.
Related
I am trying to work with getdelim() function which apperantly is the preferred method with getline() over fgets(). However, when I try to run the code below, I get undefined reference to getdelim() error.
I don't think it has anything to do with the code but rather the gcc version that I am using. So to the cmd I typed gcc -v and apperantly I have gcc version 8.1.0 (x86_64-win32-seh-rev0, Built by MinGW-W64 project)
I am not sure how old it is or if that's the problem. If so, what version of the gcc should I use and can I solve this with adding some fancy macros?
Code:
#include <stdio.h>
int main()
{
int size = 10;
char *string;
printf ("Please enter a string: ");
string = (char*)malloc(size);
getdelim (&string, &size, '-', stdin);
printf( "%s\n", string );
return 0;
}
I'm running OS X Sierra and trying to compile a c program that uses strcpy_s, but my installed clang compiler is using the c99 standard, but from what I've read strcpy_s requires c11.
Here's the code I'm trying to compile
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
if(strcpy_s(destination, sizeof(destination), source))
printf("string copied - %s",destination);
return 0;
}
And here's the command I'm using to compile
$ clang copytest.c -o copytest
copytest.c:11:5: warning: implicit declaration of function 'strcpy_s' is invalid in C99 [-Wimplicit-function-declaration]
if(strcpy_s(copied_string, sizeof(copied_string), source))
^
1 warning generated.
Undefined symbols for architecture x86_64:
"_strcpy_s", referenced from:
_main in copytest-e1e05a.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've tried compiling with the standard flag...
clang -std=c11 copytest.c -o copytest
but I get the same exact "invalid in c99" warning. I've also tried compiling with gcc instead, and I still get the same c99 warning.
I tried upgrading via homebrew which shows the following
Warning: gcc 9.2.0 is already installed and up-to-date
I have clang version 9.0.0
$ clang -v
Apple LLVM version 9.0.0 (clang-900.0.39.2)
My xcode version is Xcode 9.2, which from everything I've read should come with c11 support.
Am I doing something wrong with the compiling, is my code itself incorrect? This is the only similar question I found on here, but it didn't even have an answer. Thanks
The _s functions are an optional component of the 2011 C standard (Annex K), and, to the best of my knowledge, they have never been implemented as an integrated part of any C library. Portable code cannot rely on their availability. (Microsoft's C compilers for Windows implement an overlapping set of functions with the same names but different semantics (and sometimes even a different argument list), and at least one bolt-on implementation does exist. See this old answer, and the much longer question and answer it links to, for more detail.)
Also, the _s functions do not solve the problem that they were intended to solve (unsafe string handling); it is necessary to put actual thought into a proper fix for each use of strcpy, instead of globally search-and-replacing strcpy with strcpy_s, etc., as was the hope of the authors of Annex K. If you do put appropriate amounts of thought into a proper fix, you won't need any of the _s functions to implement it. For instance, here's a fixed version of your example program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
size_t srclen = strlen(source);
if (srclen + 1 > sizeof destination) {
fprintf(stderr, "string too long to copy - %zu bytes, need %zu\n",
sizeof destination, srclen + 1);
return 1;
} else {
memcpy(destination, source, srclen + 1);
printf("string copied - %s\n", destination);
return 0;
}
}
And here's an even better version:
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: ./test 'message of arbitrary length'\n");
return 1;
}
char *destination = strdup(argv[1]);
if (!destination) {
perror("strdup");
return 1;
}
printf("string copied - '%s'\n", destination);
free(destination);
return 0;
}
Therefore: Never use any of the _s functions. If you need to write a program that compiles on Windows with no warnings, put #define _CRT_SECURE_NO_WARNINGS 1 at the top of each file to make MSVC stop giving you bad advice.
If all, or even most, programmers wrote the suggested solutions above all the time, then these functions wouldn't be needed. We have a lot of evidence that many programmers do not write such careful code, going back to Spaf's notes on the Robert T Morris finger worm in the late 1980's.
You also would prefer not to have to duplicate 10 lines of code for every call site of strcpy. That leads to unreadable code. More so, what zwol suggests is really just an implementation of the function he claims we don't need. A good programmer would take that, stick it in a header, and name it something helpful, maybe checked_strcpy? Or even strcpy_s?
The second suggested implementation, which is purportedly better is not - it would cause an allocation when we might already have a buffer. Allocations are expensive, using this approach everywhere would be bad for perf. It also introduces new complexity because now we'd have to free every duplicated string - imagine doing that with repeated calls to strcat.
There is a fairly nicely done cross-platform implementation here:
https://github.com/intel/safestringlib
I'm also not sure whether this is actually any different, but worth taking a look - https://github.com/coruus/safeclib
In the code below if instead of a I use a number it works fine. But if i use a it gives the following error:
Cannot convert 'char(*)[a]' to 'char(*)[2]' for argument '2' to 'void displayNumbers(int, char(*)[2])'
#include <stdio.h>
void displayNumbers(int,char num[2][2]);
int main()
{
int a=2;
char num[a][a];// if i write 2 instead of a, it works fine!
displayNumbers(a,num);
return 0;
}
void displayNumbers(int a,char num[2][2])
{
printf("%c\n",a+ num[1][1]);
}
Why does using a or 2 make a difference here? I have a feeling the reason may be trivial but it would be really great if someone helps. The IDE i am using is Dev C++.
You have three primary problems.
First the declaration of displayNumber hard-codes num[2][2] defeating the purpose of using a Variable Length Array (the variable part of the name is at issue). While num[2][2] is valid, it is better written as num[a][a], or best (num*)[a] (a pointer to an array of char [a])
Next, num is completely uninitialized. What do you expect to print? Attempt to read an uninitialized value invokes Undefined Behavior.
Last, your format string in printf ("%c\n", a + num[1][1]); is suspect. The function name is displayNumber, yet you are attempting to print a character. Further, if the value is below ' ' (space, e.g. 0x20, 32), nothing will print, you would be in the Non-Printiable range. If you want to print the number, use the "%d" format specifier.
Putting it altogether, you could do something similar to:
#include <stdio.h>
void displayNumbers (int a, char (*num)[a]);
int main (void) {
int a=2;
char num[a][a];
for (int i = 0; i < a; i++)
for (int j = 0; j < a; j++)
num[i][j] = i + j;
displayNumbers (a, num);
return 0;
}
void displayNumbers (int a, char (*num)[a])
{
printf ("%d\n", a + num[1][1]);
}
Example Use/Output
$ ./bin/dispnum
4
Look things over and let me know if you have further questions.
Example Compile and Use on TDM-GCC 4.9.2
I have TDM-GCC 4.9.2 on a Win7 box. It works fine. Here is the version, compile and run on Windows 7:
C:\Users\david\Documents\dev\src-c\tmp>gcc --version
gcc (tdm-1) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
C:\Users\david\Documents\dev\src-c\tmp>gcc -Wall -Wextra -pedantic -Ofast -std=gnu11 -o bin\dispnum dispnum.c
C:\Users\david\Documents\dev\src-c\tmp>bin\dispnum
4
(I left the full directory and path information as an example that you can compile from anywhere as long as gcc.exe is in your path)
Program:
#ifndef PRINTF_H
#define PRINTF_H
#include "my_put_char.h"
int my_printf(char *str, ...);
#endif
This is my Header file for my function.
#include <stdio.h>
#include "my_put_char.h"
void my_put_char(char c)
{
fwrite(&c, sizeof(char), 1, stdout);
}
This is my putchar implementation(my_put_char.c).
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "printf.h"
int my_printf(char *str, ...)
{
if(str == NULL)
return 0;
int i;
char a;
va_list print;
va_start(print,str);
for(i = 0; str[i] ; i++)
{
if(str[i] == '%')
{
i++;
switch(str[i])
{
case 'c':
a = va_arg(print, char);
my_put_char(a);
break;
}
}
}
va_end(print);
return 0;
}
At last, this is a part of my printf implementation.
I'm testing with %c to display a character.
When I do my_print("%c", 'd'); from main.c
it compiles and displays d.
But when I do my_print("%c", "hi"); , it still compiles and displays a number.
Question:
After(or before) writing a = va_arg(print, char); Is there a way to check whether my input is a different data type?
I'm trying to display an error if my input is a different data type.
I'm on this subject for 2 days and couldn't find any answer.
Thank you so much for your time!
when I do my_print("%c", "hi"); , it still compiles and displays a number
You've got some undefined behavior, so be scared. Your my_printf would call va_arg with an argument of the bad type (expected char promoted to int, got char*).
To explain what is happening you should dive into implementation details (look into the assembler code, e.g. with gcc -Wall -fverbose-asm -O -S; study your processor, its instruction set architecture, its application binary interface and calling conventions). You don't want to do that, it could take years and is not reproducible.
Read absolutely Lattner's blog on UB, right now!
Then download C11 specification n1570....
You could also, with gcc, use some function attributes. Don't forget to compile with all warnings and debug info (gcc -Wall -Wextra -g)
after writing a = va_arg(print, char); Is there a way to check whether my input is a different data type?
No, not really and not always. But the format function attribute could help. And you could also spend months customizing GCC with your own plugin or some GCC MELT extension (that is not worth your time). Be aware of the Halting Problem and Rice's Theorem (each makes static source code program analysis so challenging). Look also into source analyzing tools like Frama-C.
I'm implementing printf function
BTW studying the source code of existing free software implementations of the C standard library (such as GNU glibc and musl-libc) could be inspirational; they are based upon syscalls(2).
I want to match the regex (?<=SEARCH_THIS=").+(?<!"\n) in C with PCRE.
However, the following code doesn't work as expected.
#include <pcreposix.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void){
regex_t re;
regmatch_t matches[2];
char *regex = "(?<=SEARCH_THIS=\").+(?<!\"\n)";
char *file = "NO_MATCH=\"0\"\nSOMETHING_ELSE=\"1\"\nSOME_STUFF=\"1\"\nSEARCH_THIS=\"gimme that\"\nNOT_THIS=\"foobar\"\nTHIS_NEITHER=\"test\"\n";
puts("compiling regex");
int compErr = regcomp(&re, regex, REG_NOSUB | REG_EXTENDED);
if(compErr != 0){
char buffer[128];
regerror(compErr, &re, buffer, 100);
printf("regcomp failed: %s\n", buffer);
return 0;
}
puts("executing regex");
int err = regexec(&re, file, 2, matches, 0);
if(err == 0){
puts("no error");
printf("heres the match: [.%*s]",matches[0].rm_eo-matches[0].rm_so,file+matches[0].rm_so);
} else {
puts("some error here!");
char buffer[128];
regerror(err, &re, buffer, 100);
printf("regexec failed: %s\n", buffer);
}
return 0;
}
The console output is:
compiling regex
executing regex
some error here!
regexec failed: No match
I verified the functionality of this regex here
Any idea what is going wrong here?
EDIT #1
Compiler Version
$ arm-merlin-linux-uclibc-gcc --version
arm-merlin-linux-uclibc-gcc (GCC) 4.2.1
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Compile Command
$ arm-merlin-linux-uclibc-gcc -lpcre ./re_test.c -o re_test.o
There are actually a few issues with your code.
First, you use %*s in an attempt to restrict the length of the printed string. However, the integer width before the s formatter is the minimum length of what gets printed; if the corresponding string's length is less than what's given, it'll be padded with spaces. If the length is greater than what's given, it'll just output the whole string. You'll need some other method of restricting the length of the outputted string (just avoid modifying *file, because file points to a constant string).
Second, you specify the REG_NOSUB option in your regcomp call, but according to the man page, this means that no substring positions are stored in the pmatch argument - thus, even if your regexec did work, the following printf would be using uninitialized values (which is undefined behavior).
Finally, I suspect the problem is that the \" and \n characters need to be doubly-escaped; i.e. you need to use \\\" and \\n in your regex string. While the code you gave worked for me (Ubuntu 14.04 x64), the doubly-escaped version also works.
Taking all of this into account, this is the output I get:
compiling regex
executing regex
no error
heres the match: [.gimme that"]