I'm attempting to run the following code:
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[]) {
/* code */
char senha [256];
if (argv[1] != NULL)
{
strcpy(senha, argv[1]);
}
char frase [256];
printf("Insira a frase: \n");
scanf("%s", frase);
int sizeS = (int)strlen(senha);
int sizeF = (int)strlen(frase);
char fraseout [sizeF+1];
int i;
int j;
for (i=0; i<=sizeF-1; i++)
{
if(j>=sizeS)
{
j=0;
}
int valF = (int)frase[i];
int valS = (int)senha[j];
valF = 32 + ((valF - 32) + (valS - 32)) % (128-32);
fraseout[i] = (char)valF;
j++;
}
fraseout[sizeF] = '\0';
printf("\"%s\" -> \"%s\"\n", frase, fraseout);
return 0;
}
When I attempt to run this on my Ubuntu 15.04 it compiles and runs perfectly. When I try to run it on a OSX Yosemite it also compiles and run flawlessly. If I, however, compile and run it on a CS50 VM although the compilation runs fine I get a Segmentation Fault error on Running. Why is this happening and why only on one singular OS?
The code works when j has an initial value of 0. This is not to be assumed on all (or any) systems, however, hence the different behavior. Initialize j.
Possible issues, with irrelevant lines removed. The uninitialized ones are likely your problem.
argv[1] != NULL is safe with C89, but is obscure and might not be on noncompliant compilers. Checking argc is more typical.
senha is left uninitialized i f the argument is not passed, which may result in buffer overflows later.
char senha [256];
if (argv[1] != NULL)
strcpy(senha, argv[1]);
Not checking the size of the buffer for input, use scanf("%255s", frase);
Not checking the return value of scanf, frase will be left uninitialized if it fails, which may result in buffer overflows later.
char frase [256];
scanf("%s", frase);
VLAs not in C89, but are in C99 and provided as an extension in GNU C89, which is the default used by gcc. This may fail to compile with strict C89 compilers.
int sizeF = (int)strlen(frase);
char fraseout [sizeF+1];
Not initialized.
int j;
This computation may yield a ", resulting in improperly quoted output.
valF = 32 + ((valF - 32) + (valS - 32)) % (128-32);
fraseout[i] = (char)valF;
printf("\"%s\" -> \"%s\"\n", frase, fraseout);
Related
i just want to ask,whats wrong with my code and why does it say segmentation fault(core dumped)? Im trying to sift all the similar letters and only print the dissimilar ones. Here's my code(with skeleton code from my prof) And here's the original instruction: "to remove all occurrences of c in s and returns the result."
#include <stdio.h>
char* clean(char* s,int c);
int main()
{
clean("banana",'x');
return 0;
}
char* clean(char* s,int c)
{
for(int i = 0; i < 6; i++)
{
if(s[i] != c)
{
printf("c",s);
s[i]++;
}
}
return s;
}
Because in
s[i]++;
s refers to "banana" (a string literal), and you're trying to modify it. Modifying a string literal has undefined behavior, and on many systems it'll just crash because the compiler places string literals in read-only memory.
With gcc you can use -Wwrite-strings to get warnings about code like that.
The segmentation fault
You get a segmentation fault because the string "banana" is a literal, which means that it is read-only.
In your code, you try to do s[i]++, which increases the value of one of the characters.. Which you can't do, because of it being read-only. without it your code compiled and ran fine.
The solution
Now to answer your question. You specified the solution should return the result, not print it out, and since the literal is read-only, we need to create a new string. I chose to use malloc so that the size of the new string matches that of the old one, but you can also allocate a fixed buffer.
The following code prints "bnn":
#include <stdio.h>
#include <string.h> // For strlen
#include <stdlib.h> // For malloc & free
char* clean(char* s, int c);
int main() {
char* result = clean("banana", 'a');
printf("%s\n", result);
free(result); // Everything allocated with malloc must be freed.
return 0;
}
char* clean(char* s, int c) {
int length = strlen(s), i = 0, j = 0;
char* result = malloc(length + 1); // +1 for null terminator.
memset(result, 0, length + 1);
for (i; i < length; i++) {
if (s[i] != c) {
result[j] = s[i];
j++;
}
}
return result;
}
Question: Write a program anagram that sorts the letters in a word, which is useful when searching for anagrams. anagram takes a single argument, which is a string containing only lower-case letters, sorts the letters alphabetically, and then prints the sorted letters. You may use any sorting algorithm you are familiar with, but you must write the sort function yourself. You may not use any sort function provided by a library.
Usage
$ ./anagram hello
ehllo
$ ./anagram positivity
iiiopsttvy
$ ./anagram abcdef
abcdef
The below code is what I have done so far but I get the error
passing char * to parameter of unsigned char converts between pointers to integer types with different sign
#include <stdio.h>
#include <string.h>
void anagram(unsigned char input[])
{
int count[256] = { 0 };
int i;
for (i = 0; input[i] != '\0'; i++)
{
count[input[i]]++;
}
for (i = 0; i < 256; i++)
{
while (count[i] > 0)
{
printf("%c", i);
count[i]--;
}
}
}
int main(int argc, char* argv[])
{
if(argc > 1)
{
anagram(argv[1]);
}
return 0;
}
The short answer to your question is you are getting the pointer sign mismatch warning because you are attempting to pass argv[1] (type char *) to anagram which you have declared with a parameter of unsigned char * (though you use input[], the practical effect is that input decays to a pointer when used as a parameter)
The simple solution while preserving the unsigned char* type for anagram is to cast argv[1] to (unsigned char *) when passed as a parameter to anagram, e.g.
anagram((unsigned char *)argv[1]);
The more practical question is "Do you really need the unsigned char* type to begin with?" While you can escape and pass non-ASCII values as the argument to your program -- is that something you expect and want to protect against by using the unsigned char* (which is 100% fine to do).
Generally, you would simply declare anagram (char *input) (which is your second alternative to eliminate the signed mismatch on the pointers) and limit your loop to looping over the valid range for ASCII characters (see ASCIItable.com)
Either way is fine so long as you handle the pointer signedness consistently. Putting that altogether and removing the magic numbers from your code, you could do something similar to the following:
#include <stdio.h>
#include <string.h>
#define CHRSET 256 /* if you need a constant, define one */
void anagram (unsigned char *input)
{
int i, count[CHRSET] = { 0 };
for (i = 0; input[i] != '\0'; i++)
count[input[i]]++;
for (i = 0; i < CHRSET; i++)
while (count[i] > 0) {
printf("%c", i);
count[i]--;
}
putchar ('\n'); /* provide a POSIX compliant newline before termination */
}
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf (stderr, "error: insufficient input\n"
"usage: %s <string>\n", argv[0]);
return 1;
}
anagram ((unsigned char *)argv[1]);
return 0;
}
(note: you can also move the output of the final newline to main, but unless you plan on smushing multiple sorted strings together by making repeated calls to anagram, then it is better left after the output of each string)
Look things over and let me know if you have further questions.
I have a C program that takes arguments from the command line. Prints the arguments in reverse order. And finds the needle/substring in the haystack. I have the following code:
Dumb.c
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "Dumb.h"
int main(int argc, char **argv)
{
int i, j, flag = 0;
for (i = 1; i < argc; i++)
{
char needle[] = "dumb";
int length = strlen(argv[i]);
for (j = length - 1; j >= 0; j--)
{
printf("%c", argv[i][j]);
argv[i][j] = tolower(argv[i][j]);
}
char *pch = strstr(argv[i], echo);
if(pch)
{
flag = 1;
}
}
if (flag == 1)
{
printf("Dumb was found!\n");
}
return 0;
}
It works perfectly when I try to run it manually from command line using: ./a.out Dumb.
But when I try to use a special test case for it, it just crashes at this line: argv[i][j] = tolower(argv[i][j]);
Here is the code for the testing:
TestLauncher.c
int unit_test(int argc, char **argv);
int main(int argc, char **argv)
{
unit_test(argc, argv);
return 0;
}
Test.c
int __hide_main__(int argc, char **argv);
int unit_test(void)
{
int retval;
char **array;
array = malloc(sizeof(char *) * 2);
array[0] = "./a.out";
array[1] = "Dumb";
retval = __hide_main__(2, array);
free(array);
return retval;
}
When you use the string literal "Dumb", it is read-only, unlike the command-line arguments. To see this, try running the following and you should get the same error:
char *arr = "Dumb";
arr[0] = 'd';
To fix this, you should copy the value of argv into a new array rather than modifying it in-place.
But when I try to use a special test case for it, it just crashes at this line: argv[i][j] = tolower(argv[i][j]);
Your program is having undefined behavior as you are trying to modify the string literal. When a program is having undefined behavior, anything can happen like it may work as expected, it may crash etc.
Change this:
array[1] = "Dumb";
to this:
array[1] = strdup("Dumb");
It works perfectly when I try to run it manually from command line using: ./a.out Dumb.
From C Standards (5.1.2.2.1p2):
The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.
So, it is perfectly fine to modify the argument vector which contains the list of the arguments passed (including program name) when running from command line.
Hence the program is working fine when running from command line.
Also, in your program unit_test function declared as:
int unit_test(int argc, char **argv);
but in the definition the signature is not matching:
int unit_test(void)
The compiler must be giving conflicting types error for this or I believe its a typo while you have edited your program before posting.
Follow the good programming practice, always check the malloc return:
array = malloc(sizeof(char *) * 2);
if (NULL == array) {
fprintf (stderr, "Failed to allocate memory");
exit(EXIT_FAILURE);
}
I am having some memory issues with printing hex in the following format: \xAA\xAB\xDC using my encryption routine.
I did some modifications, using snprintf() and strcat() in an attempt to fix the output and it worked to some degree.
This is the function I originally started out with, which is probably better than my modified version.
char *encrypt(char key, const char *a) {
char *output = malloc(strlen(a)+1);
bzero(output, strlen(a)+1);
strcpy(output, a);
char *tmp = output;
int i;
for (i = 0; tmp[i] != 0; i++) {
tmp[i] = key ^ tmp[i];
}
return output;
}
My current progress is as follows:
char *encrypt(char key, const char *a)
{
char buf[256];
char *tmp = a;
int i;
int *k;
for (i = 0; tmp[i] != 0; i++)
{
char temp[10];
k = key ^ tmp[i];
snprintf(temp, sizeof(temp), "\\x%s", k);
strcat(buf, temp);
}
return buf;
}
int main(int argc, char **argv)
{
if (argv[1] == NULL){
printf("Usage: %s <string>\n", argv[0]);
}
else printf("Encrypted string: %s\n", encrypt(0xEB, argv[1]));
return 0;
}
If anyone could point me in the right direction on how to fix the memory issue, and if the code can be improved I would appreciate that a lot.
The primary issue, in your code, buf is local to the function encrypt(). So you may not return the array from the function. Once the function finishes, the array will cease to exist and the returned address will be invalid. If the returned value is ued in the caller, it will invoke undefined behavior.
You need to define buf as a pointer and allocate dynamic memory using malloc() or family. Also, you need to free() the memory, once the usage is over.
That said,
you have defined k to be a pointer but did not allocate memory to it.
k = key ^ tmp[i]; seems meaningless, maybe you meant *k = key ^ tmp[i];
%s expects a pointer to char array (null-terminated) as argument. From that point, snprintf(temp, sizeof(temp), "\\x%s", k); also looks wrong. What you need is snprintf(temp, sizeof(temp), "\\x%d", *k); to print the int value.
Instead of:
int *k;
k = key ^ tmp[i];
snprintf(temp, sizeof(temp), "\\x%s", k);
use this:
unsigned char k;
k = key ^ tmp[i];
snprintf(temp, sizeof temp, "\\x%02X", k);
Note that you also have other changes to make regarding buf. Firstly you never initialize it, so you are appending to junk. And you never check that you didn't overflow it.
Also you attempt to return this from a function, however, since it is a local variable, it ceases to exist when the function returns.
See this thread for some suggestions of how to get freshly-written string out of a function. You could use malloc(256) in the same vein as your first attempt (and remember to replace sizeof buf with the mallocated length, in the snprintf call).
It'd be more robust to use unsigned char instead of char for both the key and the message. An example of the issues is that on x86 or x64, char has a range of -128 to 127 so when you supply 0xEB (i.e. 235) this is an out-of-range assignment which is not well-defined.
But on common systems you will get away with using char because they tend to define out-of-range assignment by using 2's complement and truncating excess bits, which works in your situation.
I'm relatively new to C (and completely new to StackOverflow - hey guys!), and this segfault has been giving me no surcease of sorrow for the past few hours (DevC++ on a windows machine). It's just a simple palindrome prime program, but it's really giving me a hard time. I'm not generally a novice programmer like it seems here, but... Good god. Now I remember why I wanted to get away from C++ and to Python so quickly.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
FILE *outputFile;
char buffer[81];
char* strrev();
int bytesWritten;
char* strI = 0;
char *strrev(char str[])
{
char *p1 =NULL;
char *p2 =NULL;
if (! str || ! *str)
return str;
for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
{
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
}
return str;
}
main()
{
int isPrime(int);
int i,j;
outputFile = fopen("DD:OUTPUT", "w");
if (outputFile == NULL)
{
printf("open error: %d/%s\n", errno, strerror(errno));
exit(99);
}
for (i=1; i<15000; i++)
{
if (isPrime(i)==1)
{
bytesWritten = sprintf(buffer,"%d is primepal!\n",i);
fwrite(buffer, 1, bytesWritten, outputFile);
}
}
fclose(outputFile);
return 0;
}
int isPrime(int myInt)
{
int loop;
for (loop = 2; loop < myInt/2+1; loop++)
sprintf(strI, "%s%d", 10, myInt);
{
if (myInt%loop==0 && (atoi(strrev(strI))-myInt)==0)
{
return 0;
}
return 1;
}
}
I apologize ahead of time if this is a dumb question, and the answer is very obvious -- but I've officially hit the limit where no matter how logical an answer, I've been coding the same problem for too long for it to make any sense. And also, segfaults are horrible beasts. Thank you ahead of time for anything you have to offer!
~ Jordan
The line sprintf(strI, "%s%d", 10, myInt); is likely crashing.
You have not allocated any space for strI, it's defined as char* strI = 0; Make it a char[64] , or a suitable size.
You're giving the wrong arguments to sprintf, "%s%d" says the first parameter should be a string ("%s") , but you give it an int. Change %s to %d
Some other issues:
Don't use *p1 ^= *p2; hack to to swap variables, there's many cases where this does not work. Do it properly with a temp variable.
main() calls isPrime(), but there's no prototype for isPrime at that time. Place int isPrime(int myInt); somewhere before main().
The prototype for your strrev function should be char *strrev(char str[]); and not char *strrev()
Segfaults don't have to be as bad as you're experiencing. Compile the program with debugging symbols (add -g to gcc) and run it in gdb. After the segfault, type bt in gdb and press enter. It will tell you the exact line of your segfault.
for (loop = 2; loop < myInt/2+1; loop++)
sprintf(strI, "%s%d", 10, myInt);
{
if (myInt%loop==0 && (atoi(strrev(strI))-myInt)==0)
You might want to double-check where you've got that brace in relation to the for. This isn't python, and indentation alone doesn't cut it.