CString format return weird character - c-strings

student1's name print out correctly "alice", but student2's name print out in "weird characters".
char * student;
student = "alice";
printf("student1 : %s\n", student);
CString student2;
student2 = "alice";
student = (char *)( LPCSTR )student2;
printf("student2:%s\n", student);
why after cast it with "(char *)( LPCSTR )" , it returns weird character instead ?

First, this program worked for me.
However, that does not mean it is correct.
With MBCS, you typically use _T macros to be sure your strings are declared properly.
Here is my simple re-write of your code:
#include "stdafx.h"
#include "atlstr.h"
int _tmain(int argc, _TCHAR* argv[])
{
LPCSTR student = _T("alice"); // Use the provided LPCSTR type instead of char*.
printf("student1 : %s\n", student);
CString student2(_T("alice")); // Initialize a CString with the _T macro
student = (LPCSTR)student2; // LPCSTR is typedef to char*.
// So you effectively had (char*)(char*)student2;
// TypeCasting something twice to the same type is stupid.
printf("student2:%s\n", student);
return 0;
}
Output
student1 : alice
student2:alice

Related

Pointer Functions in C: initialization of foo from incompatible pointer type

I'm working with C, and not allowed to use C++. Currently, I'm trying to implement some level of OOP in C. I'm currently working on trying to implement polymorphism and inheritance.
I've spent the majority of the day reading up on how my goals are possible through the use of function pointers. I am attempting to print the members variables of both structs as seen here:
RecordObject.h
typedef struct SuperRecordObject
{
char *Id;
char *date;
char *cases;
char *deaths;
void (*ptrPrintRecord)(char *id, char *date, char *cases, char *deaths, char *names_fr, char *names_en);
} SuperRecord;
typedef struct ChildRecordObject
{
SuperRecord super;
char *names_fr;
char *names_en;
} ChildRecord;
I have defined the function ptrPrintRecord in this file:
RecordObject.c
#include <stdio.h>
#include "RecordObject.h"
void ptrPrintRecord(char *id, char *date, char *cases, char *deaths, char *names_fr, char *names_en)
{
//char *record;
printf(" %s | %s | %s | %s | %s | %s\n", id, date, cases, deaths, names_fr, names_en);
//return record;
}
And I try to use the function in this file, as such:
DataLayer.c
#include <stdio.h>
#include <string.h>
#include "RecordObject.h"
/* more code here */
void(*fun_ptr)(char*,char*,char*,char*,char*,char*) = &record.super.ptrPrintRecord; //
(*fun_ptr)(record.super.Id, record.super.date, record.super.cases, record.super.deaths, record.names_fr, record.names_en);
/* more code here */
However, when I compile (using GCC), I get this warning which causes a crash.
warning: initialization of 'void (*)(char *, char *, char *, char *, char *, char *)' from incompatible pointer type 'void (**)(char *, char *, char *, char *, char *, char *)' [-Wincompatible-pointer-types]
62 | void(*fun_ptr)(char*,char*,char*,char*,char*,char*) = &record.super.ptrPrintRecord;
I've ran some other pointer functions in other files to mess around and test it, and the only thing I can think of as to what's going on here is it's maybe got something to do with how strings work in C?
You have an extraneous & in your attempted function pointer assignment. The ptrPrintRecord member of your structure is already a function pointer of the correct type, so you don't need the & - which would give the address of that pointer.
Just use:
void(*fun_ptr)(char*, char*, char*, char*, char*, char*) = record.super.ptrPrintRecord; // No &
As a side note, your use of ptrPrintRecord as that member (function pointer) and also as the name of an actual function (with the same 'signature') is likely to cause some issues, further down the road.
Furthermore, you need to actually initialize that member (pointer) to a valid function address before copying it to something you then call (as also with the other members of the structure). Here's a small main (using your other code) that works:
int main()
{
ChildRecord record;
record.super.ptrPrintRecord = ptrPrintRecord; // See my note about the name clash!
record.super.Id = "ID";
record.super.date = "today";
record.super.cases = "cases";
record.super.deaths = "deaths";
void(*fun_ptr)(char*, char*, char*, char*, char*, char*) = record.super.ptrPrintRecord; //
// To call the pointed-to function, we can just use the pointer name:
fun_ptr(record.super.Id, record.super.date, record.super.cases, record.super.deaths, record.names_fr, record.names_en);
return 0;
}

How to declare the data type for variable arguments?

I'm trying to assign data type to world but unable to figure it out.
#include <stdarg.h>
#include <stdio.h>
#define TRACE(arg) TraceDebug arg ;\
void TraceDebug(const char* format, ...);
void TraceDebug(const char* format, ...)
{
char buffer[256];
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
int main(void)
{
int a =55;
TRACE((Hello,a));
return 0;
}
Below is the error statement in detail.
main.c: In function 'main':
main.c:28:12: error: 'Hello' undeclared (first use in this function)
TRACE((Hello,a));
^
main.c:13:32: note: in definition of macro 'TRACE'
#define TRACE(arg) TraceDebug arg ;\
^
main.c:28:12: note: each undeclared identifier is reported only once for each function it appears in
TRACE((Hello,a));
^
main.c:13:32: note: in definition of macro 'TRACE'
#define TRACE(arg) TraceDebug arg ;\
^
Is there anyway possible to declare Hello as a variable, after declaring I need to get the address of the variable.
In simple I want to change the below code into a variadic function arguments
for example #define QU(arg1,arg2) as #define QU(arg1,...) since variadic macro is not supported am using variadic functions.
#define TRACE(arg1) QU arg1
#define QU(arg1,arg2) {static const char arg1; \
printf("%p\n",(void*)&arg1);\
printf("%d\n",arg2);}\
int main(void)
{
int aaa =333;
int bbb =444;
TRACE((Hello,aaa));
TRACE((Hello2,bbb));
return 0;
}
1) (title) How to declare the data type for variable arguments?
2) (1st question) I'm trying to assign data type to world but unable to figure it out.
1) The data type for the variadic argument (represented by the ellipses: ... ) is always the type of the variable preceding the ellipses . For this prototype:
int variadicFunc(int a, const char *b, ...);
^^^^^^^^^^ ^^^
type assumes the type const char *
2) From content of your question only, the answer could be to be use a typedef statement:
typedef char World; // a new type 'World' is created
But there are clarifications in the comments:
if i change the string to variable i can reduce the memory size,... (you)
You want to have a variable argument list to pass variables existing in your program that you want to place on a Trace list for debugging
purposes. (is that close?)... (me)
(is that close?) yes, that's the thing am trying to do... Are you always going to pass the same type to this function? Ahh, type will
be like TRACE(("Hello", a,"world")); (you)
It appears you want to enter a variable number of either string literals, or string variables as function arguments, then for those items to be placed into variables, then the addresses of those variables to be stored in a file, for the purpose of saving space.
The following code illustrates how you can pass a variable number of strings (in different forms) into a function, and have the address and content retained into a struct. From this, you should be able to adapt from what I have done here, to something more useful to your needs. Note, I have reserved the first string argument to be used a file location to store addresses.
#define MAX_LEN 200
typedef struct {
unsigned int addr;
char str[MAX_LEN];
} DATA;
int variadicFunc(int argCount, const char *str, ...);
int main(void)
{
char a[] = {"this is a string"};
char b[] = {"another string"};
char c[] = {"yet another string"};
// count non-variable v1 v2 v3 v4
variadicFunc(4, ".\\storage.txt", a, b, "var string", c);
// ^count of variable argument list
return 0;
}
int variadicFunc(int argCount, const char *str, ...)
{
va_list arg;
int i;
char sAddr[10];
DATA *d = calloc(argCount, sizeof(*d));
va_start(arg, str);
FILE *fp = fopen(str, "w");//using first string as filename to populate
if(fp)
{
for(i=0;i<argCount;i++)
{
// retain addresses and content for each string
strcpy(d[i].str, va_arg(arg, const char *));
d[i].addr = (unsigned int)&d[i].str[i];
sprintf(sAddr, "%X\n", d[i].addr);
fputs(sAddr, fp);
}
fclose(fp);
}
return 0;
}

C struct pointers return

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_BUFFER_SIZE 100
typedef struct config_struct config_t ;
struct config_struct{
char name[20];
char ip[20];
int port;
char log[100];
};
int main(int argc, char *argv[]) {
config_t config;
read_config_file(argv[1], &config);
return 0;
}
int read_int_from_config_line(char* config_line) {
int val = atoi(config_line);
return val;
}
void read_str_from_config_line(char* config_line, char* val) {
strncpy(val,config_line, MAX_BUFFER_SIZE);
}
void read_config_file(char* config_filename, config_t *config) {
FILE *fp;
char *value, buffer[MAX_BUFFER_SIZE];
fp = fopen("./settings.conf", "r");
while (fgets(buffer, MAX_BUFFER_SIZE, fp) != NULL) {
if(!strcmp(buffer,"NAME")) {
read_str_from_config_line(value, &(config->name));
}
if(!strcmp(buffer,"PORT")) {
&(config->port) = read_int_from_config_line(value);
}
}
}
I try to compile this code and it gives me a incompatible pointer type at read_str_from_config_line(value , &(config->name)); and lvalue required as left operand of assignment &(config->port) = read_int_from_config_line(value);
I am trying to return the stuct back to the main program but I'm having problem with the struct pointers.
Any solution for it to be solve?
PS: The code is a mess as I trying to shorten it. Any help will be good as I am still a beginner to C programming.
Thanks
The & operator means "take the address of the object to the right".
This:
&(config->port)
means "take the address of the port member of the structure pointed to by config.
You don't want to take the address, you just want to assign to the member. That's just:
config->port = ...
This is the same as (*config).port, but nobody writes it like that since the arrow operator is so convenient.
read_str_from_config_line(value, &(config->name));
confg->name is declared as a char array, which naturally decays to a pointer to the first element (of type "pointer-to-char") if you omit the &:
read_str_from_config_line(value, config->name);
Taking its address explicitly instead results in a pointer of type pointer-to-array-of-20-chars, which is not the same type as pointer-to-char - which is why you are getting an error. This is a common source of confusion in C; in general, you should not take the address of an array (although it does have legitimate use cases).
In this line:
&(config->port) = read_int_from_config_line(value);
You are taking the address of the port member of the structure pointed at by config, which is a non-lvalue pointer. It looks like you are actually trying to assign to the member, so the line should read:
config->port = read_int_from_config_line(value);

error: conflicting types for 'removeSpaces'

I want to write a program which will verify whether the string is palindrome or not.
But there is an error when I try to pass strings[0] to removeSpaces function which will remove spaces.
Why does 'comflicting types error' occurs? What is wrong?
The whole code of programm:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * removeSpaces(char *); // prototype
int main()
{
char *strings[2]; // created array of pointers
strings[0] = strdup("a man a plan a canal panama");
printf("%s\n", strings[0]);
strings[1] = removeSpaces(strings[0]);
printf("%s\n", strings[0]);
/* (in future) it will display "amanaplanacanalpanama" */
free(strings[0]);
return 0;
}
char * removeSpaces(char * str[0]) // an ERROR occurs here
{
/* some code */
return -1; // in case of fault
}
Your code has two issues:
Your function declaration and definition conflicted. You don't have to specify
char *str[0], char *str is enough and it should match with your declaration at the top.
You are returning -1 instead of a pointer which is not a valid pointer in its form. If some fault occurs I would recommend you to return NULL instead.
-1 is an integer. But however, you can also use 0 instead, because that defaults to (void *)0 nothing but NULL.
change like this:
char * removeSpaces(char * str) // an ERROR occurs here
{
/* some code */
return NULL; // return NULL in case of fault instead of -1
}
When you declare a function, each parameter needs a type and a name. Your removeSpaces function takes a single parameter of type char *, so you'd declare it as
char * removeSpaces(char * str)
Remember, the function doesn't know that you'll be passing it the first element of an array; it just knows you'll give it a pointer to a string of characters.
It's also the convention in C to return a null pointer when its data is missing or would be invalid. So instead of returning -1 if there's an error, you should return NULL.
The declaration:
char * removeSpaces(char *);
Is different from the definition:
char * removeSpaces(char * str[0]);
Change the prototype:
char * removeSpaces(char *);

Cannot return and assign char array to pointer in C

char *test = "hello";
test = change_test("world");
printf("%s",test);
char* change_test(char *n){
printf("change: %s",n);
return n;
}
im trying to pass a 'string' back to a char pointer using a function but get the following error:
assignment makes pointer from integer without a cast
what am i doing wrong?
A function used without forward declaration will be considered having signature int (...). You should either forward-declare it:
char* change_test(char*);
...
char* test = "hello";
// etc.
or just move the definition change_test before where you call it.
printf() prints the text to the console but does not change n. Use this code instead:
char *change_test(char *n) {
char *result = new char[256];
sprintf(result, "change: %s", n);
return result;
}
// Do not forget to call delete[] on the value returned from change_test
Also add the declaration of change_test() before calling it:
char *change_test(char *n);
You're converting an integer to a pointer somewhere. Your code is incomplete, but at a guess I'd say it's that you're not defining change_test() before you use it, so the C compiler guesses at its type (and assumes it returns an integer.) Declare change_test() before calling it, like so:
char *change_test(char *n);
thanks a bunch guys! didnt think i would have this problem solved by lunch. here is the final test class
/* standard libraries */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* change_test(char*);
int main(){
char *test = "hello";
test = change_test("world");
printf("%s",test);
return (EXIT_SUCCESS);
}
char* change_test(char *n){
return n;
}

Resources