Switch based on a character in pointer

M

Mark Hobley

I am trying to rewrite a section of code within an existing program.

This is a section of code (simplified and non-working) showing the structure
that I am trying to achieve:

char *ParseString (char *instring)
{
char *ptr1=instring

if (instring == NULL)
return instring;

while (*ptr1) {
switch(*ptr1) {
case iscntrl(*ptr1)
*ptr1=' ';
case isspace(*ptr1)
*ptr1=' ';
case '+'
*ptr1=' ';
case '%'
*ptr1=' ';
}
ptr1++;
}
}

I am trying to first use the iscntrl and isspace functions to evaluate *ptr1.
From this I will overwrite *ptr1 with a character. Then I want to compare *ptr1
to a series of known characters via a switch statement, and then do some
processing based upon that, changing *ptr1.

How is the best way to achieve this ?

Please advise.

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/
 
S

Sandeep

Mark said:
I am trying to rewrite a section of code within an existing program.

This is a section of code (simplified and non-working) showing the structure
that I am trying to achieve:

simplified and "compilable" code would be appreciated.
char *ParseString (char *instring)
{
char *ptr1=instring

if (instring == NULL)
return instring;

while (*ptr1) {
switch(*ptr1) {
case iscntrl(*ptr1)
*ptr1=' ';
case isspace(*ptr1)
*ptr1=' ';
case '+'
*ptr1=' ';
case '%'
*ptr1=' ';
}
ptr1++;
}
}

For a switch statement, the "case has to be labeled by integer valued
constants or constant expression" ( K & R 3.4 ).

case iscntrl(*ptr1) and isspace(*ptr1) would not meet this requirement.


It would be great if you can post a code that could be "compiled"
(ofcourse with the errors that you are facing) rather than outlining
it.
 
J

Jack Klein

I am trying to rewrite a section of code within an existing program.

This is a section of code (simplified and non-working) showing the structure
that I am trying to achieve:

char *ParseString (char *instring)
{
char *ptr1=instring

if (instring == NULL)
return instring;

while (*ptr1) {
switch(*ptr1) {
case iscntrl(*ptr1)

You can't do this here. The value in a case statement must be a
compile-time integer constant expression. It cannot be the value of
any object, whether read through a pointer or not.
*ptr1=' ';
case isspace(*ptr1)
*ptr1=' ';
case '+'
*ptr1=' ';
case '%'
*ptr1=' ';
}
ptr1++;
}
}

I am trying to first use the iscntrl and isspace functions to evaluate *ptr1.
From this I will overwrite *ptr1 with a character. Then I want to compare *ptr1
to a series of known characters via a switch statement, and then do some
processing based upon that, changing *ptr1.

How is the best way to achieve this ?

Please advise.

When you can't use a switch/case control structure for reasons like
this, the alternative is if/else if.

while (*ptr1) {
if (iscntr(*ptr1)
{ /* do what you want */ }
else if (isspace(*ptr1)
{ /* do what you want */ }
else if (*ptr1 == '+')
{ /* whatever */ }
else if (*ptr1 == '%')
{ /* etcetera */ }
else
{ /* final else provides equivalent of default: in switch */ }
ptr1++;
}

You say your example is simplified, but if all of your actions are the
same (replace by the same character) there are various tweaks that
might or might not be more efficient on your implementation:

static const char repl [] = "+%"; /* and any others */

while (*ptr1)
{
if ( (isspace(*ptr1)
|| (isctrl(*ptr1))
|| (NULL != strchr(repl, *ptr1))
{ *ptr1 = ' '; }
++ptr1;
}

Warning the above is uncompiled and untested, so there's probably
something wrong with it.
 
P

pete

Mark Hobley wrote:
while (*ptr1) {
switch(*ptr1) {
case iscntrl(*ptr1)
*ptr1=' ';
case isspace(*ptr1)
*ptr1=' ';
case '+'
*ptr1=' ';
case '%'
*ptr1=' ';
}
ptr1++;
}

while (*ptr1) {
if (iscntrl((unsigned char)*ptr1)) {
*ptr1 = ' ';
} else {
if (isspace((unsigned char)*ptr1)) {
*ptr1 = ' ';
} else {
switch (*ptr1) {
case '+':
*ptr1 = ' ';
break;
case '%':
*ptr1 = ' ';
break;
default:
break;
}
}
}
ptr1++;
}
 
K

Keith Thompson

I am trying to rewrite a section of code within an existing program.

This is a section of code (simplified and non-working) showing the structure
that I am trying to achieve:

char *ParseString (char *instring)
{
char *ptr1=instring

if (instring == NULL)
return instring;

while (*ptr1) {
switch(*ptr1) {
case iscntrl(*ptr1)
*ptr1=' ';
case isspace(*ptr1)
*ptr1=' ';
case '+'
*ptr1=' ';
case '%'
*ptr1=' ';
}
ptr1++;
}
}

I am trying to first use the iscntrl and isspace functions to
evaluate *ptr1. From this I will overwrite *ptr1 with a
character. Then I want to compare *ptr1 to a series of known
characters via a switch statement, and then do some processing based
upon that, changing *ptr1.

A switch statement can only compare an integer value to a series of
constants. You can have multiple case labels, but there's no
mechanism for specifying a range or calling a function.

I also note that you don't have a "break;" on each case, which means
each case will fall through to the next one. Assuming you don't want
it to fall through, your while loop can be replaced by:

while (*ptr1) {
if (iscntrl(*ptr1)) {
*ptr1=' ';
}
else if (isspace(*ptr1)) {
*ptr1=' ';
}
else if (*ptr1 == '+') {
*ptr1 = ' ';
}
else if (*ptr1 == '%') {
*ptr1 = ' ';
}
ptr1++;
}

You might also do something like this:

while (*ptr1) {
if (iscntrl(*ptr1) || isspace(*ptr1) ||
*ptr1 == '+' || *ptr1 == '%')
{
*ptr1 = ' ';
}
ptr1++;
}

or like this:

while (*ptr1) {
switch (*ptr1) {
case '+':
case '%':
*ptr1 = ' ';
break;
default:
if (iscntrl(*ptr1)) {
*ptr1=' ';
}
else if (isspace(*ptr1)) {
*ptr1=' ';
}
break;
}
ptr1++;
}

depending on what your full code looks like.
 
M

Mark Hobley

pete said:
while (*ptr1) {
if (iscntrl((unsigned char)*ptr1)) {
*ptr1 = ' ';
} else {
if (isspace((unsigned char)*ptr1)) {
*ptr1 = ' ';
} else {
switch (*ptr1) {
case '+':
*ptr1 = ' ';
break;

Cheers Pete. That was exactly what I wanted to achieve. I had written
something similar, but in my version, I had overlooked the (unsigned char) bit,
This was causing a compile error, when the compiler reached the line after the
first case statement.

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/
 
C

Carl R. Davies

Mark said:
char *ParseString (char *instring)
{
char *ptr1=instring

if (instring == NULL)
return instring;

while (*ptr1) {
switch(*ptr1) {
case iscntrl(*ptr1)
*ptr1=' ';
case isspace(*ptr1)
*ptr1=' ';
case '+'
*ptr1=' ';
case '%'
*ptr1=' ';
}
ptr1++;
}
}

How about a for loop so the declaration, test and increment of prt1 are
together:

for( char *ptr1=instring; *ptr1; ptr1++ )
{
/* switch stuff */
}
 
K

Keith Thompson

pete said:
while (*ptr1) {
if (iscntrl((unsigned char)*ptr1)) {
*ptr1 = ' ';
} else {
if (isspace((unsigned char)*ptr1)) {
*ptr1 = ' ';
} else {
switch (*ptr1) {
case '+':
*ptr1 = ' ';
break;
case '%':
*ptr1 = ' ';
break;
default:
break;
}
}
}
ptr1++;
}

It's very common to write if-else chains on a single indentation
level:

while (*ptr1) {
if (iscntrl((unsigned char)*ptr1)) {
*ptr1 = ' ';
}
else if (isspace((unsigned char)*ptr1)) {
*ptr1 = ' ';
}
else {
switch (*ptr1) {
case '+':
*ptr1 = ' ';
break;
case '%':
*ptr1 = ' ';
break;
default:
break;
}
}
ptr1++;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top