我设法从程序中创建以下输出:
7.86 ( 8Hm,), 6.82 ( 4Hm,),12.1 ( 1Hs,).
我想要添加空格或删除空格,具体取决于我指向的字符。 sscanf会允许你这样做吗?
我只是想知道在本文中插入和删除空格的最简单方法是什么。例如,我想删除(
和' num'之间的空格。例如8
,但在H
和'字母'之间提供一个空格。例如m
。到目前为止,我的代码看起来像这样:
typedef struct node {
int i;
char array[SIZE];
struct node* link;
} node;
node* format(void)
{
int count = 0;
int size = list_size(data, sizeof(data)) / 4;
for (node* ptr = head; ptr != NULL; ptr = ptr->link)
{
int i;
int j;
for (i = 0, j = 0; i < sizeof(ptr->array); i++, j++)
{
if (ptr->array[0] == ' ' && count == 0)
{
count++;
j--;
}
else if (ptr->array[i] == ' ' && ptr->array[i-1] == '.')
{
j--;
ptr->array[i] = ',';
}
else if (ptr->array[i] == ',' && ptr->array[i-1] == ')')
{
if (count == size)
{
ptr->array[i] = '.';
}
}
ptr->array[j] = ptr->array[i];
}
count++;
}
return head;
}
请注意,上面是一个大小为3的链表,我创建了后者,以便能够交换&#34;组&#34;字符然后以特定方式反转顺序。如果我先将所有内容传回一个数组,那么格式化会更容易吗?
非常感谢任何提示/建议!
答案 0 :(得分:0)
最简单的方法是使用sscanf
正确解析字符串,然后将其打印到另一个字符串。以你的方式手动解析字符串将无法获得可观察到的速度/内存增益,并且只会添加大量代码。
#include<stdio.h>
int main(){
char str[]= "7.86 ( 8Hm,), 6.82 ( 4Hm,),12.1 ( 1Hs,).";
float f1, f2, f3;
int i1, i2, i3;
sscanf(str, "%f ( %dHm,), %f ( %dHm,),%f ( %dHs,).", &f1, &i1, &f2, &i2, &f3, &i3);
printf("%f ( %dHm,), %f ( %dHm,),%f ( %dHs,).\n", f1, i1, f2, i2, f3, i3);
return 0;
}
scanf
函数功能强大,您可以看到可以使用它们来解析格式化的字符串。当您在此示例中运行代码时,它将打印:
7.860000 ( 8Hm,), 6.820000 ( 4Hm,),12.100000 ( 1Hs,).
它的工作方式是scanf
可以忽略字符。所以它读取第一个float然后忽略空格,忽略括号,读取int,忽略Hm等等。
我的printf
正在以与输入相同的方式形成字符串。您可以调整它以满足您的要求。您还应该搜索并限制十进制数字。但基本的想法是,您从字符串中获取所需的数据,然后您可以按照您希望的方式打印该数据。
答案 1 :(得分:0)
尽力了解您目前在ptr-array
中拥有的内容,然后了解如何完成重新格式化,您似乎想要in-place
只需更新ptr->array
以保持更新的格式字符串,然后您可以构建一个格式正确的缓冲区来替换当前的ptr->array
。
注意:更好的解决方案是将ptr->array
中的值分隔为实际的单独值,并将其作为链接列表的一部分保存,您可以静态声明要保存的结构数组您的values
和units
(这是我对7.86 (8Hm,)
的最佳猜测。这将允许您以任何方式格式化值,而不是被array
中的内容所困扰例如:
#define USIZE 8
typedef struct values {
double value;
char[USIZE];
} values;
typedef struct node {
int i;
char array[SIZE];
values *vals;
struct node* link;
} node;
或,例如:
typedef struct node {
int i;
char array[SIZE];
values vals[3];
struct node* link;
} node;
无论如何,您的原始问题是如何重新格式化ptr->array
之后的现有'('
删除空格,并在以下示例数据中将'8Hm'
分隔为'8H m'
:
7.86 ( 8Hm,), 6.82 ( 4Hm,),12.1 ( 1Hs,).
鉴于您正在迭代列表中的每个节点,这个重新格式化可能只在您收集/存储所有节点后才运行一次。一种方法是构建一个新缓冲区,以新格式保存array
,然后用格式正确的array
替换新的buffer
。
是的,有很多方法可以做到这一点,但如果您的重新格式标准有限,只需使用经过验证的真正的 inch-worm 方法向下走array
指针即可具有所需格式字符的新缓冲区与其他任何格式一样简单灵活。
下面,该示例创建了一个新缓冲区(buf[SIZE]
)从ptr->array
复制/替换/删除字符,然后将ptr->array
替换为buf
的内容。
注意:我没有在任何数据上运行此操作,因此您可能需要稍微调整一下逻辑。这仅仅是为了向您展示一种可以使用的方法,并使其尽可能接近您的问题的解决方案(尽我所知)。
注意2:如果您是isupper
,则可以使用islower
或ctype.h
替换下面的上/下案例条件不限于特定的标题。此外,下面的memcpy
将需要string.h
,但如果这是一个问题,可以重新编写以便在没有它的情况下进行复制。
node* format(void)
{
/* for each node in list */
for (node* ptr = head; ptr != NULL; ptr = ptr->link)
{
/* declare a pointer to `ptr->array` and `buf` */
char *p = ptr->array;
char *pend = p + SIZE;
char buf[SIZE] = {0};
char *bp = buf;
/* for each char in ptr->array */
while (p < pend)
{
/* if not the first char */
if (p > ptr->array)
{
/* if current char is ' ' */
if (*p == ' ')
{
/* if previous char is one of the following */
if (*(p - 1) == '.') *bp++ = ',';
if (*(p - 1) == ')') *bp++ = '.';
if (*(p - 1) == '(') { p++; continue; } /* remove ' ' after '(' */
}
/* if current is lower case & prior is upper, separate */
else if (('a' <= *(p - 1) && *(p - 1) <= 'z') && ('A' <= *p && *p <= 'Z'))
{
*bp++ = ' ';
*bp++ = *p;
}
/* default - copy current to buf */
else
*bp++ = *p;
}
p++; /* advance to next char */
}
/* copy formatted string to ptr->array */
memcpy (ptr->array, buf, SIZE);
}
return head;
}
注3:如果SIZE
是全球#define
,则将sizeof (ptr->array)
替换为SIZE
。