Casting a const void* pointer parameter into a const char* pointer, in memchr function - pointers

I have to reproduce the functioning of the memchr function, which returns the pointer of the first int c occurence.
Of course, size_t n argument has been measured by func strlen before being sent to ft_memchr func parameter.
But I keep on getting this compiling error (compiled with a main.c) "
ft_memchr.c:10:21: error: operand of type 'const void' where arithmetic or pointer type is required
if ((const char *)s[i] == (const char)c)
"
I'm clearly missing something... It seems I can't cast the const void* parameter into a const char* or even a char*, why is that ?
Thank you.
#include <string.h>
void *ft_memchr(const void *s, int c, size_t n)
{
size_t i;
i = 0;
while (i < n)
{
if ((const char *)s[i] == (const char)c)
return ((char *)s + i);
}
return (NULL);
}

Related

X is not a valid template argument for 'const char*' because it is not the address of a variable

I'm trying to use the resources of a temporary class object as a template parameter. But apparently this doesn't work:
godbolt
#include <iostream>
constexpr size_t size(const char* s)
{
int i = 0;
while(*s!=0) {
++i;
++s;
}
return i;
}
template <const char* S>
struct string_struct
{
constexpr string_struct() {
for (int i=0; i < size(S); ++i) {
buf_[i] = S[i];
}
}
constexpr const char* get() {
return buf_;
}
char buf_[size(S)] = {0};
};
constexpr const char some_chars[] = "100";
constexpr auto compose_string()
{
string_struct<some_chars> other_str{};
return string_struct<other_str.get()>;
}
int main()
{
compose_string();
}
gcc 12.1 complains:
<source>: In function 'constexpr auto compose_string()':
<source>:32:41: error: 'other_str.string_struct<(& some_chars)>::get()' is not a valid template argument for 'const char*' because it is not the address of a variable
32 | return string_struct<other_str.get()>;
| ^
<source>:29:16: error: invalid return type 'auto' of 'constexpr' function 'constexpr auto compose_string()'
29 | constexpr auto compose_string()
|
Of course this is a contrived example. What I actually want to do is extend an enhanced version of string_struct recursively. But how can I use its resources for template instantiation? And if that is somehow possible, how do I deduce the return type of a function that returns string_structs (and in the recursive case a string_struct, that is instantiated with another string_struct, that is instantiated with another sstring_struct...)?
Is it even possible?

How does one use qsort to sort a char containing pathnames/files based on their bytes?

I basically wrote a code in which I take two command line arguments one being the type of file that I want to search in my directory and they other being the amount I want(which is not implemented yet, but I can fix that)
The code is like so:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define sizeFileName 500
#define filesMax 5000
int cmpfunc( const void *a, const void *b) {
return *(char*)a + *(char*)b;
}
int main( int argc, char ** argv) {
FILE * fp = popen( "find . -type f", "r");
char * type = argv[1];
char * extension = ".";
char* tExtension;
tExtension = malloc(strlen(type)+1+4);
strcpy(tExtension, extension);
strcat(tExtension, type);
// printf("%s\n",tExtension);
int amount = atoi(argv[2]);
//printf("%d\n",amount);
char buff[sizeFileName];
int nFiles = 0;
char * files[filesMax];
while(fgets(buff,sizeFileName,fp)) {
int leng = strlen(buff) - 1;
if (strncmp(buff + leng - 4, tExtension, 4) == 0){
files[nFiles] = strndup(buff,leng);
//printf("\t%s\n", files[nFiles]);
nFiles ++;
}
}
fclose(fp);
printf("Found %d files\n", nFiles);
long long totalBytes = 0;
struct stat st;
// sorting based on byte size from greatest to least
qsort(files, (size_t) strlen(files), (size_t) sizeof(char), cmpfunc);
for(int i = 0;i< nFiles; i ++) {
if(0!= stat(files[i],&st)){
perror("stat failed:");
exit(-1);
}
totalBytes += st.st_size;
printf("%s : %ld\n",files[i],st.st_size);
}
printf("Total size: %lld\n", totalBytes);
// clean up
for(int i = 0; i < nFiles ; i ++ ) {
free(files[i]);
}
return 0;
}
So far I have every section set up properly, upon running the code say $./find ini 5, it would print out all the ini files followed by their byte size(it's currently ignore the 5). However, for the qsort(), I'm not exactly sure how I would sort the contents of char * files as while it holds the pathnames, I had to use stat to get the byte sizes, how would I print out a sorted version of my print statements featuring the first statement being the most bytes and finishes at the least bytes?
If we suppose your input is valid, your question could be simplified with:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define filesMax 5000
int cmpfunc(const void const *a, const void *b) { return *(char *)a + *(char *)b; }
int main(void) {
int nFiles = 4;
char *files[filesMax] = {"amazing", "hello", "this is a file", "I'm a bad file"};
qsort(files, strlen(files), sizeof(char), cmpfunc);
for (int i = 0; i < nFiles;; i++) {
printf("%s\n", files[i]);
}
}
If you compile with warning that give you:
source_file.c:11:23: warning: incompatible pointer types passing 'char *[5000]' to parameter of type 'const char *' [-Wincompatible-pointer-types]
qsort(files, strlen(files), sizeof(char), cmpfunc);
^~~~~
qsort() expect the size of your array (or in your case a subsize) and it's also expect the size of one element of your array. In both you wrongly give it to it. Also, your compare function doesn't compare anything, you are currently adding the first bytes of both pointer of char, that doesn't make a lot of sense.
To fix your code you must write:
qsort(files, nFiles, sizeof *files, &cmpfunc);
and also fix your compare function:
int cmpfunc_aux(char * const *a, char * const *b) { return strcmp(*a, *b); }
int cmpfunc(void const *a, void const *b) { return cmpfunc_aux(a, b); }
also size should be of type size_t:
size_t nFiles = 0;
Don't forget that all informations about how to use a function are write in their doc.
how would I print out a sorted version of my print statements featuring the first statement being the most bytes and finishes at the least bytes?
Your code don't show any clue that your are trying to do that, you are currently storing name file and only that. How do you expect sort your file with an information you didn't acquired ?
However, that simple create a struct that contain both file name and size, acquire information needed to sort it and sort it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <inttypes.h>
struct file {
off_t size;
char *name;
};
int cmpfunc_aux(struct file const *a, struct file const *b) {
if (a->size > b->size) {
return -1;
} else if (a->size < b->size) {
return 1;
} else {
return 0;
}
}
int cmpfunc(void const *a, void const *b) { return cmpfunc_aux(a, b); }
#define filesMax 5000
int main(void) {
size_t nFiles = 4;
struct file files[filesMax] = {{42, "amazing"},
{21, "hello"},
{168, "this is a file"},
{84, "I'm a bad file"}};
qsort(files, nFiles, sizeof *files, &cmpfunc);
for (size_t i = 0; i < nFiles; i++) {
printf("%s, %" PRId64 "\n", files[i].name, (intmax_t)files[i].size);
}
}
The function cmpfunc() provided adds the first character of each string, and that's not a proper comparison function (it should give a opposite sign value when you switch the parameters, e.g. if "a" and "b" are the strings to compare, it adds the first two characters of both strings, giving 97+98 == 195, which is positive on unsigned chars, then calling with "b" and "a" should give a negative number (and it again gives you 98 + 97 == 195), more on, it always gives the same result ---even with signed chars--- so it cannot be used as a sorting comparator)
As you are comparing strings, why not to use the standard library function strcmp(3) which is a valid comparison function? It gives a negative number if first string is less lexicographically than the second, 0 if both are equal, and positive if first is greater lexicographically than the second.
if your function has to check (and sort) by the lenght of the filenames, then you can define it as:
int cmpfunc(char *a, char *b) /* yes, you can define parameters as char * */
{
return strlen(a) - strlen(b);
}
or, first based on file length, then lexicographically:
int cmpfunc(char *a, char *b)
{
int la = strlen(a), lb = strlen(b);
if (la != lb) return la - lb;
/* la == lb, so we must check lexicographycally */
return strcmp(a, b);
}
Now, to continue helping you, I need to know why do you need to sort anything, as you say that you want to search a directory for a file, where does the sorting take place in the problem?

Is it possible to have a const reference to a nonconst char pointer?

Is it possible to have a const reference to *argv and iterate through the array of pointers argv?
For the code below, I get the following warning:
a reference of type "const char *& (not const-qualified) cannot be initialized with a value of type "char *"
After building, I get this error message:
cannot convert from 'char *' to 'const char *&'.
#import <iostream>
using std::cout;
using std::endl;
int main (int argc, char * argv []) {
for (const char *& c = *argv; *c != '\0'; ++c) {
cout << *c << endl;
}
return 0;
}
I am confused because I know it is possible to have a const reference to a non-const variable like so:
int i = 42;
int &r1 = i;

Error in function clbuildprogram... (it returns -11)

I've created a bubble sort code. The clbuildprogram in the user function createProgram is giving an error
My kernel looks like:
__kernel void sort_kernel(__global const float *a, __global const float *b)
{
const int n=100;
int j;
float temp;
int gid = get_global_id(0);
b[gid]=a[gid];
for(j=0; j < n-gid; j++)
{
if(b[j+1]<b[j])
{
temp=b[j];
b[j]=b[j+1];
b[j+1]=temp;
}
}
}
clbuildprogram is giving an error as per the runtime error.
***Error in kernel: :1:1: error: unknown type name '_kernel'
_kernel void sort_kernel(__global const float *a, __global const float *b) //, ^
:1:9: error: expected identifier or '('
_kernel void sort_kernel(__global const float *a, __global const float *b) //,
^
:21:3: error: expected external declaration
}
^
:23:1: error: expected external declaration } ^
:23:1: error: expected external declaration***
Please tell me what is the error and how can I rectify it...?
You missed a _ in your program. The error is obvious.I dont think the code pasted here is the same as you run.
Correct your _kernel to __kernel in your program.

character pointer vs int pointer

How this works:
int main()
{
int * ch = NULL;
cout<<"Hello"<<ch<<"World"<<endl;;
cout<<"Hello world1"<<endl;
return 0;`
}
Whereas this fails:
int main()
{
char * ch = NULL;
cout<<"Hello"<<ch<<"World"<<endl;;
cout<<"Hello world1"<<endl;
return 0;`
}
For most pointer types,
cout << ptr;
prints an implementation-defined representation of the pointer value, usually an address in hexadecimal format. But for char*, the operator<<() is overloaded to interpret the pointer as a pointer to the first char in a 0-terminated char array, and print it like printf("%s", ptr); would.
Printing the address a null pointer points to is harmless, following a null pointer to interpret the bytes starting from where it points to is undefined behaviour, and more often than not leads to a segmentation fault.

Resources