I'm learning C. I'm messing around with pointers to understand how they work, but I can't really understand why I'm getting the errors that I explain ahead.
The code is:
#include <stdio.h>
#define MAT_COLS 13
#define MAT_ROWS 12
void test(char **, size_t, size_t);
int main(void)
{
char *matrix[MAT_ROWS] = {"############", "############", "############", "############", "############", "############", "############", "############", "############", "############", "############", "############"};
test(matrix, MAT_ROWS, MAT_COLS);
}
void test(char **Mat, size_t mat_rows, size_t mat_cols)
{
printf("\n%s", Mat[3]);
printf("\n%c", Mat[3][5]);
printf("\n%s", (Mat + 3)); //strange output
printf("\n%c", *(*(Mat + 3) + 5));
fflush(stdout);
Mat[3][5] = 46; //seg. fault
}
The output is:
############
#
`UUUU
#
I got two unexpected behavior:
The strange output of the line printf("\n%s", (Mat + 3));: `UUUU
The last line of the function test Mat[3][5] = 46; give me segmentation fault.
I used the debugger and Mat+3 is the address of a string of matrix, but it outputs that strange string.
What is the problem?
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;
}
I'm trying to use a function to assign space and fill that space (or at least some of it) with characters to form a string. Within the function I make a call to malloc, and within the same function I assign characters to the given space. The following code gives the general gist of what I'm doing:
#define INITIAL 10
int func(char **s);
int
main(int argc, char **argv) {
char *s;
int n;
n = func(&s);
printf("Done\n");
return 0;
}
int
func(char **s) {
int i;
*s = (char*)malloc(INITIAL*sizeof(char));
assert(*s);
for (i=0; i<5; i++) {
printf("i=%d\n", i);
*s[i] = 'a'; /*'a' is an arbitrary char for this example */
}
return i;
}
The output of this code is:
i=0
i=1
i=2
Segmentation fault: 11
The reason I have my function return an int is because I ultimately want the function to return the length of the string I have formed.
I'm completely unsure why I am getting a segmentation fault; it seems I have assigned enough space to fit the next char in. It also seems weird to me that it stops at i=2.
If anyone could identify the mistakes I have made I would greatly appreciate it!
Instead of
*s[i] = 'a';
you want
(*s)[i] = 'a';
*s[i] is equivalent to *(s[i]). That is, it treats s as an array of strings and gives you the first character of the string at index i.
*s[i] first calculate s[i], which won't be valid place for i!=0, then dereference it and try to put 'a' there. It may cause Segmentation Fault.
Try changing *s[i] to (*s)[i].
Postfix [] has higher precedence than unary *, so *s[i] is being parsed as *(s[i]), which isn't what you want; you want to dereference s and index into the result, so you need to explicitly group the * operator with s: (*s)[i].
You may want to use size_t instead of an int. Or ssize_t if you need the function to return a negative value:
#include <stdio.h>
#include <stdlib.h>
#define INITIAL 10
ssize_t func(char **);
int main(void)
{
char *s;
if((func(&s)) == -1)
{
printf("An error occurred\n");
return 1;
}
printf("Done\n");
free(s);
return 0;
}
ssize_t func(char **s)
{
size_t i = 0;
if ( INITIAL < 1 )
return -1;
if (!(*s = malloc(INITIAL*sizeof(char))))
return -1;
for (i=0; i< 5; i++) {
printf("i=%zu\n", i);
(*s)[i] = 'a';; /*'a' is an arbitrary char for this example */
}
return i;
}
I am playing around a bit in C and trying to write a test program for kind of oop in c programming. I get the Error of the headline in Visual Studio 2010. In using gcc i don't get this error.
Can anyone point me to what i am doing wrong, besides using the wrong language for oop, and other off topic suggestions.
It seems like the error occurs when i free the top object in string_dispose, but i am not shure if that really says a lot about the location of the error.
Also any suggestions regarding code improvements are welcome. Using array syntax is not an option, because i want to try out pointer arithmetic.
The header file "strings.h":
#ifndef STRINGS_H
#define STRINGS_H
struct strings
{
char* s;
int len;
};
typedef struct strings string;
void string_init(string* s, char* chars, int len);
string* string_new(char* chars, int len);
void string_dispose(string* s);
#endif
The source file "strings.c":
#include "strings.h"
#include <stdlib.h>
void string_init(string* self, char* chars, int len)
{
int i;
self->s = (char*)malloc((len + 1) * sizeof(char*));
for (i = 0; i < len; i++)
{
*(self->s + i) = *(chars + i);
}
*(self->s + len) = '\0';
self->len = len;
}
string* string_new(char* chars, int len)
{
string* self;
self = (string*)malloc(sizeof(string*));
string_init(self, chars, len);
return self;
}
void string_dispose(string* self)
{
free(self->s);
free(self);
}
The main file:
#include <stdlib.h>
#include <stdio.h>
#include "strings.h"
int main(int argc, char* argv)
{
string* s;
int n = 5;
char* x = (char*)malloc((n + 1) * sizeof(char*));
x[0] = 'f';
x[1] = 'u';
x[2] = 'b';
x[3] = 'a';
x[4] = 'r';
x[5] = '\0';
s = string_new(x, n);
printf("the string: %s\n", s->s);
printf("the length: %d\n", s->len);
string_dispose(s);
printf("This is way more important");
return 0;
}
When you try to allocate memory for string, you only allocate enough memory for a pointer (string*):
self = (string*)malloc(sizeof(string*));
You should allocate sizeof(string) instead, since you want enough space to store the whole struct, not just a pointer to one. Since sizeof(string*) is smaller than sizeof(string), the other code writes outside of the allocated area, causing heap corruption.
Similarly, when mallocing memory for the characters, the size should be (len + 1) * sizeof(char).
I have the following program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 255
char * decrypt(char *p, int key){
char *tmp;
for(int i = 0; p[i] != '\0'; i++){
tmp[i] = p[i]-key;
}
return tmp;
}
int main(void){
printf("Hallo Welt!");
printf("%s\n", decrypt("ibmmp", 1));
return EXIT_SUCCESS;
}
When I compile it with gcc -Wall i get the Warning tmp could get uninitialized in this function [-Wmaybe-uninitialized] tmp[i] = p[i]-key(translated from german) and segmentation fault (core dumped) ./crypto when i run it
What is causing that error?
I know this quesion has been asked many times, but i could not fix this warning, because other people had different sourcecodes and i couldn't adapt it to my problem.
You need to allocate 'tmp' and then, keeping with good 'c' coding, check that the allocation was successful. I assume you have MAX defined so you can set an upper-bound on the length of your string, so I use that below. If MAX is intended to be the number of characters without a null, then you need to 'malloc(MAX +1)'. If it is intended to include NULL, then just leave the code as defined below. You also want to decide what to return on failure of the malloc. I return NULL, but you may want to do something different depending on your needs.
Also be aware, that this function is returning allocated memory, so someone needs to free it so you aren't leaking memory.
char * decrypt(char *p, int key){
char *tmp;
tmp = (char *) malloc(MAX);
if(!tmp)
return NULL;
for(int i = 0; p[i] != '\0'; i++){
tmp[i] = p[i]-key;
}
return tmp;
}
Allocate memory for tmp before using it. Make sure you null-terminate the string before returning it.
// Make the input a const string.
// char * decrypt(char *p, int key){
char * decrypt(char const* p, int key){
char *tmp = malloc(strlen(p) + 1); // Allocate memory
int i = 0;
for( ; p[i] != '\0'; i++){
tmp[i] = p[i]-key;
}
tmp[i] = '\0'; // null terminate.
return tmp;
}
Make sure you deallocate the memory. Just using
printf("%s\n", decrypt("ibmmp", 1));
will result in a memory leak.
int main(void){
printf("Hallo Welt!");
char* dec = decrypt("ibmmp", 1)
printf("%s\n", dec);
free(dec); // Deallocate memory.
return EXIT_SUCCESS;
}
So I'm working on a program where the function reads in from stdio, and keeps reading in characters in chunks of n characters.
So far I've gotten it so that everything is stored in a character array called buffer. For the next step, I need to sort each chunk of n characters. For example the string cats/ndogs/n should be split as cats/n dogs/n if n =5, and then qsort() needs to alphabetize it. This is how I'm calling qsort():
qsort (buffer, (line-2)*n*(sizeof(char)),n,compare);
Where (line-2)*n*sizeof(char) gives the total number of items in the array buffer; 10 in this case.
This is my compare function:
int compare (const void * a, const void * b)
{
return (strcmp(*(char **)a, *(char **)b));
}
When I run this, however, I always get a seg fault in strcmp(). Any ideas why?
This is the loading code:
while (!feof(stdin))
{
for (i = 0; i < n; i++)
{
char l = getchar();
if (l != EOF)
{
if ((i == 0) && (line != 1))
{
success = (int *)realloc(buffer, line*n*(sizeof(char)));
}
buffer[(n*(line-1))+i] = l;
}
}
line = line + 1;
}
Silly question, but are your strings null terminated? You seem to only have a newline on the end.
Also, you probably only need "strcmp((char *)a, (char *)b)" as the extra *s look to be redundant to me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buffer[] ="333000222555111777888666999444";
int mycmp(void *l, void*r);
int main(void)
{
/* note: sizeof buffer is 31,
** but the integer division will round down
** , ignoring the extra nul-byte */
qsort(buffer, (sizeof buffer/3), 3, mycmp);
printf ("[%s]\n", buffer);
return 0;
}
int mycmp(void *l, void *r)
{
return memcmp(l,r,3);
}