如何在Cim中将C风格的printf转换为C ++风格的cout

时间:2016-06-05 01:31:49

标签: c++ vim

我交出了一些遗留代码,首先我想知道是否可以更改

之类的内容
printf("test %d\n", var);

std::cout << "test " << var << std::endl;

它们中有很多并且手动完成它们非常耗时。有没有办法使用vim来实现这一目标?

我得到的最远的是

:%s/printf(\(.*\), \(.*\));/std::cout << \1 << \2 << std::endl;/g

但这只会让我

std::cout << "test %d\n" << var << std::endl;

我可以将clang格式应用于代码,因此在printf中我可以保证逗号后总是有空格。在此示例中,空格介于逗号和var之间。

理想情况下,这个vim命令能够检测百分号以了解其中有多少变量,并且还检测\ n以知道何时用std :: endl替换它。请指教。

4 个答案:

答案 0 :(得分:1)

这实际上比看起来更难,特别是如果你有更复杂的格式与字段宽度说明符或其他类似的东西,或更糟糕的"%["格式。如果格式字符串的参数比简单变量或文字更复杂,例如,如果你有函数调用,那么它也很复杂。

但是对于 简单 格式化字符串和参数,例如问题中显示的printf调用,它并不难做到一种脚本语言。您获取格式化字符串并将其放在字符串变量中,然后获取所有参数并将它们作为字符串放在另一个变量中。在逗号上拆分参数字符串,你有一个参数列表。

然后迭代格式化字符串,当你点击'%'字符后面没有另一个'%'字符时,然后打印格式化字符串直到那一点并从中获取第一个参数参数列表。然后继续扫描格式化字符串,并在点击格式化序列时从其列表中获取每个相应的参数。

答案 1 :(得分:1)

我在捕获之外匹配了%d\n",并在替换中添加了一个空格和结束。

:%s/printf(\(.*\) \S\+, \(.*\));/std::cout << \1 " << \2 << std::endl;/g

答案 2 :(得分:1)

您可以尝试编写宏。

首先,转换&#34;%[插入此处]&#34;以cout格式。

:reg
--- Registers
"f   0f%2xmcf"f,dwdw`ci" << ^[pa << "^[

那么这对宏键F的作用是

  1. 0f%转到该行的开头,找到第一个百分号(假设%没有以任何其他方式使用,遗憾的是)
  2. 2xmc删除%d部分,然后将当前位置存储在标记c的行中。
  3. f"f,找到字符串的结尾,然后找到第一个逗号。
  4. dwdw删除逗号,然后删除变量名称。这将允许存储变量,以便以后粘贴。
  5. [backtick]c转到标记c。
  6. 行中的存储位置
  7. i" << ^[" <<插入字符串并退回到命令模式。
  8. pa << "^[粘贴存储的变量名称,然后插入字符串<< "
  9. 所以,最终的结果就是这个

    printf("test %d\n", var); // Before
    printf("test " << var << "\n"); // After
    

    在另一个宏键R上,简单地多次重放宏F(比如说100)。如果您的变量少于100个,那么它将无法完成宏,因为f%将会失败。

    :reg
    --- Registers
    "r   100@f
    

    所以,一个例子是

    printf("test %d %d %d %d %d\n", var, var1, var2, var3, var4); // Before
    printf("test " << var << " " << var1 << " " << var2 << " " << var3 << " " << var4 << "\n"); // After
    

    现在编写一个宏C来将开始和结束转换为C ++!

    :reg
    --- Registers
    "c   0trcwcout << ^[f(x$F)x
    
    1. 0tr转到行首,找到UNTIL first r。这是在不同缩进级别的情况下。我们将定位在p中的printf
    2. cwcout << ^[printf更改为cout <<并转到命令模式。
    3. f(x(中找到printf(并将其删除。
    4. $F)x转到该行的末尾,找到最后一个)并将其删除。
    5. 这给出了:

      printf("test " << var << " " << var1 << " " << var2 << " " << var3 << " " << var4 << "\n"); // Before
      cout << "test " << var << " " << var1 << " " << var2 << " " << var3 << " " << var4 << "\n"; // After
      

      要将它们组合在一起,创建另一个宏T,它找到printf,运行宏C,然后运行宏F.它按此顺序完成,这样如果早期部分失败,其余的命令不会跑。

      :reg
      --- Registers
      "t   /printf^M@c@r
      

      运行此宏T 3次会执行以下操作:

      // Before
      printf("test %d\n", var);
      printf("test %d %d %d %d %d\n", var, var1, var2, var3, var4);
      printf("test %d %d\n", var, var2);
      
      // After
      cout << "test " << var << "\n";
      cout << "test " << var << " " << var1 << " " << var2 << " " << var3 << " " << var4 << "\n";
      cout << "test " << var << " " << var2 << "\n";
      

      这个解决方案并不完美,它假定百分比没有以任何其他格式使用,并且必须为每个printf手动重复(垃圾邮件@@)。我希望它至少是有用的,并展示了vim的力量。

答案 3 :(得分:0)

答案需要更通用! 因此,我们可以使用vim函数来检测%%d%f%s字符以及\n\r之类的转义序列字符。

只是一个样本的伪代码。

        :function ConvertToCPP()
        :let a = getline('.')
        : while a doesn't contain % or \ characters
        :    take any number of  \n and put as endl at end of line, if any
        :   remove off the % characters.
        : put << in between each of them
        :   call setline ('.', a)
        :return 1
        :end function
不,你可以用范围来调用这个函数,这样它就可以轻松地替换它们。

    :10,20ConvertToCPP()